C4 架構圖 - Time Compass DSPy 系統¶
本文件使用 C4 Model 四層架構描述 Time Compass DSPy 系統的設計。
C1 System Context(系統上下文)¶
graph TB
User["👤 使用者"]
GoogleAPI["🔵 Google Calendar/Tasks API"]
MoodleAPI["📚 Moodle API"]
subgraph System ["🎼 Time Compass Orchestrator"]
Router["Router"]
Emotion["EmotionSupport"]
Summary["Summary"]
Scheduling["Scheduling"]
end
User -->|"user_input<br/>dialog_history"| Router
Router -->|"pipeline_description"| User
Emotion -->|"emotion_reply"| User
Summary -->|"summary_text"| User
Scheduling -->|"draft_plan / action_description<br/>constraints_and_missing_info<br/>questions<br/>next_steps_suggestion"| User
System -->|"讀取日程、任務"| GoogleAPI
System -->|"讀取課程事件"| MoodleAPI 輸出欄位流(使用者接收):
| 來源模組 | 輸出欄位 | 說明 |
|---|---|---|
| Router | pipeline_description | 1~3 句話的流程說明 |
| EmotionSupport | emotion_reply | 溫柔的情緒安撫回應 |
| Summary | summary_text | 區間回顧的文字總結 |
| Scheduling | draft_plan / action_description | 方案或可執行行動 |
constraints_and_missing_info | 缺資訊、假設、風險 | |
questions | 追問題目 | |
next_steps_suggestion | 後續建議步驟 |
角色與責任:
| 角色 | 說明 |
|---|---|
| 使用者 | 提供自然語言輸入(user_input)、對話歷史(dialog_history) |
| Time Compass Orchestrator | 核心容器,管理 Router、EmotionSupport、Summary、Scheduling 的通訊與輸出組裝 |
| Google API | 日曆、任務資料來源 |
| Moodle API | 課程、作業事件來源 |
C2 Container(容器分解)¶
graph TD
User["👤 使用者"]
User -->|"user_input<br/>dialog_history"| Orch["🎼 Orchestrator<br/>(主容器)"]
Orch --> Router["Router<br/>(DSPy Module)"]
Router -->|"pipeline<br/>pipeline_description"| Orch
Orch --> Emotion["EmotionSupport<br/>(DSPy Module)"]
Emotion -->|"emotion_reply"| Orch
Orch --> Summary["Summary<br/>(DSPy Module)"]
Summary -->|"summary_text"| Orch
Orch --> Scheduling["Scheduling<br/>(DSPy Module)"]
Scheduling -->|"draft_plan / action<br/>questions"| Orch
Orch -->|"final_reply"| User
Router -.->|"InteractionContext"| Emotion
Emotion -.->|"InteractionContext"| Summary
Summary -.->|"InteractionContext"| Scheduling 容器說明:
| 容器 | 型別 | 職責 |
|---|---|---|
| Orchestrator | DSPy Application | 統籌整個對話流程。呼叫 Router 決定 pipeline,依序執行各模組,蒐集結果 |
| Router | DSPy Module | 判斷使用者意圖、情緒強度,決定後續執行模組(pipeline) |
| EmotionSupport | DSPy Module | 情緒安撫與陪伴,自然銜接後續步驟 |
| Summary | DSPy Module | 時間段回顧與成就總結 |
| Scheduling | DSPy Module | 複合模組,包含路由、方案生成、追問等子流程 |
訊息流¶
Orchestrator.forward(user_input, dialog_history)
↓
【第 1 步】Router 決策
├─ 輸入: user_input, dialog_history
├─ 判斷: 是否進入 EmotionSupport、Summary、Scheduling?
└─ 輸出: pipeline = ["EmotionSupport", "Summary"], pipeline_description = "..."
↓
【第 2 步】組裝 InteractionContext
├─ 封裝: user_input, dialog_history, pipeline, ...
└─ 準備: 按 pipeline 順序依序傳給各模組
↓
【第 3 步】依序執行 Pipeline
├─ 若 EmotionSupport 在 pipeline:執行並蒐集 emotion_reply
├─ 若 Summary 在 pipeline:執行並蒐集 summary_text
└─ 若 Scheduling 在 pipeline:執行並蒐集草案 / 行動 / 追問
↓
【第 4 步】組裝最終回覆
├─ 整合各模組輸出
├─ 選擇性支援 streaming(逐字推送)
└─ 回傳 final_reply
C3 Component(組件細節)¶
Router Module¶
graph TD
Input["user_input<br/>dialog_history"]
Input --> Sig["RouterSignature<br/>(判斷意圖)"]
Sig --> Decide{"決策節點"}
Decide -->|"低落"| Em1["Pipeline +=<br/>EmotionSupport<br/>(前置)"]
Decide -->|"普通/高漲"| NoEm1["不加<br/>前置 Emotion"]
Decide -->|"需要 Summary"| Sum["Pipeline +=<br/>Summary"]
Decide -->|"需要 Scheduling"| Sched["Pipeline +=<br/>Scheduling"]
Decide -->|"都不需"| Empty["Pipeline = []<br/>(無關請求)"]
Em1 --> Final["Router 输出:<br/>pipeline<br/>pipeline_description"]
NoEm1 --> Final
Sum --> Final
Sched --> Final
Empty --> Final 簽章: RouterSignature - 輸入: user_input, dialog_history - 輸出: pipeline_description (string), pipeline (List[str])
詳見 USER-DIALOG-FLOW.md → Router 決策流程
Scheduling Module(複合)¶
graph TD
Input["InteractionContext"]
Input --> SchedulingRouter["SchedulingRouter<br/>(判斷任務等級)"]
SchedulingRouter --> Decide{"是否 L3<br/>(行動級)?"}
Decide -->|"L3(行動級)"| DraftAction["DraftAction Signature<br/>(生成可執行行動)"]
Decide -->|"L1/L2(想法/方案級)"| DraftPlan["DraftPlan Signature<br/>(生成草案)"]
DraftAction --> AskQ["AskQuestion Signature<br/>(若有缺資訊)"]
DraftPlan --> AskQ
AskQ --> Output["回傳結果:<br/>questions<br/>next_steps_suggestion"] 子簽章: - SchedulingRouterSignature - 任務等級判斷,決定進入 DraftPlan 或 DraftAction - DraftPlanSignature - L2 級方案生成(含候選時段) - DraftActionSignature - L3 級行動生成(含首步驟指南) - AskQuestionSignature - 資訊不足時追問
詳見 USER-DIALOG-FLOW.md → SchedulingRouter 流程
Orchestrator 內部流通¶
graph TD
Start["Orchestrator.forward<br/>(user_input,<br/>dialog_history)"]
Start --> Ctx["組裝<br/>InteractionContext"]
Ctx --> CtxData["{\n user_input: ...,\n dialog_history: ...,\n pipeline: [],\n current_pipeline_index: 0,\n previous_signature_output: {}\n}"]
CtxData --> Call_Router["呼叫 Router"]
Call_Router --> Got_Pipeline["取得 pipeline"]
Got_Pipeline --> Loop["依 pipeline 順序<br/>逐一執行模組"]
Loop --> InLoop["for each module in pipeline:"]
InLoop --> UpdateCtx["更新 InteractionContext<br/>(傳入用戶與前一結果)"]
UpdateCtx --> CallModule["呼叫 module(ctx)"]
CallModule --> Collect["蒐集輸出至<br/>previous_signature_output"]
Collect --> Next["執行下一個模組"]
Next --> Done{"還有模組<br/>未執行?"}
Done -->|"是"| InLoop
Done -->|"否"| Assemble["組裝最終 final_reply"]
Assemble --> Stream{"需要<br/>Streaming?"}
Stream -->|"是"| DoStream["dspy.streamify()<br/>逐字推送"]
Stream -->|"否"| DirectReturn["直接回傳"]
DoStream --> End["回傳 RouterResponse"]
DirectReturn --> End C4 Code(程式碼層級)¶
Orchestrator 簽章與介面¶
# 輸入簽章
class OrchestrationInput:
user_input: str # 使用者提問
dialog_history: str # 對話歷史
# 輸出簽章
class OrchestrationOutput:
pipeline_description: str # Router 的流程說明
final_reply: str # 最終回覆(整合後)
streaming_chunks: Optional[AsyncGenerator[str, None]] # 若支援 streaming
# 主方法
async def orchestrator.forward(
user_input: str,
dialog_history: str = ""
) -> OrchestrationOutput:
"""
主編排入口。管理 Router、模組執行、結果蒐集。
"""
pass
InteractionContext 資料結構¶
@dataclass
class InteractionContext:
"""各模組間通訊的標準封裝"""
# 使用者與對話
user_input: str # 使用者這輪輸入
dialog_history: str # 對話歷史記錄
# 流程管理
pipeline: List[str] # Router 決定的模組清單
current_pipeline_index: int # 當前執行位置
previous_signature_output: Dict[str, Any] # 前一模組輸出
# 資源數據
time_interval_data: Optional[str] # 可用時間窗(Scheduling 用)
# 中繼狀態
emotion_state: Optional[str] # 情緒評估結果
task_level: Optional[str] # 任務等級(L1/L2/L3)
各 Signature 規格¶
# ========== Router ==========
class RouterSignature(dspy.Signature):
"""判斷使用者意圖、決定後續 pipeline"""
dialog_history: str = dspy.InputField(description="對話歷史")
user_input: str = dspy.InputField(description="使用者輸入")
pipeline_description: str = dspy.OutputField(
description="1~3 句話描述接下來的步驟"
)
pipeline: List[str] = dspy.OutputField(
description="要執行的模組: ['EmotionSupport', 'Summary', 'Scheduling']"
)
# ========== EmotionSupport ==========
class EmotionSupportSignature(dspy.Signature):
"""溫柔的情緒安撫"""
interaction_context: InteractionContext = dspy.InputField()
emotion_reply: str = dspy.OutputField(
description="溫柔、正常化感受的回應,自然銜接後續步驟"
)
# ========== Summary ==========
class SummaryWriterSignature(dspy.Signature):
"""區間回顧"""
interaction_context: InteractionContext = dspy.InputField()
time_interval_data: str = dspy.InputField()
summary_text: str = dspy.OutputField(description="總結文本")
# ========== Scheduling ==========
class SchedulingRouterSignature(dspy.Signature):
"""任務等級判斷"""
interaction_context: InteractionContext = dspy.InputField()
catch_and_rephrase: str = dspy.OutputField(description="重述意圖")
ai_can_do: str = dspy.OutputField(description="AI 可做的動作摘要")
task_level: str = dspy.OutputField(description="L1/L2/L3")
class DraftPlanSignature(dspy.Signature):
"""L2 方案生成"""
interaction_context: InteractionContext = dspy.InputField()
draft_plan: str = dspy.OutputField(description="草案說明(含候選時段)")
constraints_and_missing_info: str = dspy.OutputField(
description="缺資訊、假設、風險"
)
class DraftActionSignature(dspy.Signature):
"""L3 行動生成"""
interaction_context: InteractionContext = dspy.InputField()
action_description: str = dspy.OutputField(description="可執行的行動描述")
start_instructions: str = dspy.OutputField(description="首步驟指南")
constraints_and_missing_info: str = dspy.OutputField()
class AskQuestionSignature(dspy.Signature):
"""資訊不足時追問"""
constraints_and_missing_info_from_draft: str = dspy.InputField()
interaction_context: InteractionContext = dspy.InputField()
questions: str = dspy.OutputField(description="追問題目")
next_steps_suggestion: str = dspy.OutputField(description="下一步建議")
實作位置¶
| 容器 / 簽章 | 程式碼路徑 |
|---|---|
| Orchestrator | src/time_compass/domain/orchestrator.py |
| Router | src/time_compass/domain/router.py |
| EmotionSupport | src/time_compass/domain/emotion.py |
| Summary | src/time_compass/domain/summary.py |
| Scheduling | src/time_compass/domain/scheduling/ |
| InteractionContext | src/time_compass/domain/models/ |
資料流總結¶
使用者輸入
↓
Orchestrator.forward()
↓
Router.forward()
├─ 產出: pipeline, pipeline_description
└─ 寫入 InteractionContext
↓
組裝標準 InteractionContext
↓
Loop: 依 pipeline 順序執行
├─ EmotionSupport (若在 pipeline)
│ └─ 輸出: emotion_reply
│
├─ Summary (若在 pipeline)
│ └─ 輸出: summary_text
│
└─ Scheduling (若在 pipeline)
├─ SchedulingRouter
│ └─ 輸出: catch_and_rephrase, ai_can_do, task_level
│
├─ DraftPlan 或 DraftAction
│ └─ 輸出: draft_plan / action_description + constraints
│
└─ AskQuestion
└─ 輸出: questions, next_steps_suggestion
↓
Orchestrator 蒐集所有輸出
↓
組裝最終 final_reply
↓
(可選) 若啟用 streaming,逐字推送
↓
回傳給使用者
更多詳節: - USER-DIALOG-FLOW.md - 決策流程詳解 - SIGNATURE-DIRECTORY.md - 完整簽章規格