feat(learning): add learning runtime with pattern mining
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
115
backend/app/agents/learning/retrospector.py
Normal file
115
backend/app/agents/learning/retrospector.py
Normal file
@@ -0,0 +1,115 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from app.agents.schemas.learning import SessionRetrospective
|
||||
|
||||
|
||||
def _classify_task_type(query_text: str) -> str:
|
||||
normalized = (query_text or "").lower()
|
||||
if any(token in normalized for token in ("总结", "分析", "对比", "report", "analyze")):
|
||||
return "analysis"
|
||||
if any(token in normalized for token in ("安排", "提醒", "日程", "todo", "task")):
|
||||
return "planning_or_execution"
|
||||
if any(token in normalized for token in ("文档", "资料", "年报", "search", "查")):
|
||||
return "retrieval"
|
||||
return "general"
|
||||
|
||||
|
||||
def build_session_retrospective(
|
||||
*,
|
||||
request_id: str,
|
||||
session_id: str,
|
||||
user_query: str,
|
||||
state: dict[str, Any] | None,
|
||||
runtime_context: dict[str, Any] | None = None,
|
||||
) -> SessionRetrospective:
|
||||
state = state or {}
|
||||
if hasattr(runtime_context, "model_dump"):
|
||||
runtime_context = runtime_context.model_dump(mode="json")
|
||||
runtime_context = runtime_context or {}
|
||||
skill_shortlist = state.get("skill_shortlist") or []
|
||||
used_skill_names = [
|
||||
item.get("skill_name")
|
||||
for item in skill_shortlist
|
||||
if isinstance(item, dict) and item.get("skill_name")
|
||||
]
|
||||
|
||||
task_refs = []
|
||||
for task in (state.get("completed_tasks") or [])[:4]:
|
||||
if isinstance(task, dict):
|
||||
task_refs.append(
|
||||
{
|
||||
"task_id": task.get("task_id"),
|
||||
"title": task.get("title"),
|
||||
"status": task.get("status"),
|
||||
}
|
||||
)
|
||||
|
||||
event_refs = []
|
||||
for event in (state.get("event_trace") or [])[:8]:
|
||||
if isinstance(event, dict):
|
||||
event_refs.append(
|
||||
{
|
||||
"event_type": event.get("event_type"),
|
||||
"task_id": event.get("task_id"),
|
||||
"agent_id": event.get("agent_id"),
|
||||
}
|
||||
)
|
||||
|
||||
verification_evidence = []
|
||||
for evidence in (state.get("verification_evidence") or [])[:6]:
|
||||
if isinstance(evidence, dict):
|
||||
verification_evidence.append(evidence)
|
||||
|
||||
verification_status = state.get("verification_status")
|
||||
execution_mode = state.get("execution_mode")
|
||||
primary_agent = state.get("current_agent") or "master"
|
||||
retrospective_shortlist = state.get("retrospective_shortlist") or []
|
||||
|
||||
summary_parts = [
|
||||
f"本轮请求按 {execution_mode or 'unknown'} 模式处理",
|
||||
f"主要负责 agent 为 {primary_agent}",
|
||||
]
|
||||
if verification_status:
|
||||
summary_parts.append(f"验证结果为 {verification_status}")
|
||||
if used_skill_names:
|
||||
summary_parts.append(f"命中技能候选 {', '.join(used_skill_names[:3])}")
|
||||
if retrospective_shortlist:
|
||||
summary_parts.append(f"参考了 {len(retrospective_shortlist)} 条历史复盘")
|
||||
|
||||
final_response = state.get("final_response")
|
||||
outcome = "completed" if final_response else "failed"
|
||||
if not final_response and verification_status == "passed":
|
||||
outcome = "completed"
|
||||
if final_response and verification_status == "skipped":
|
||||
outcome = "partial"
|
||||
|
||||
return SessionRetrospective(
|
||||
retrospective_id=request_id,
|
||||
user_id=str(runtime_context.get("user_id") or ""),
|
||||
conversation_id=session_id,
|
||||
response_message_id=request_id,
|
||||
query_text=user_query,
|
||||
final_response=final_response,
|
||||
summary=";".join(summary_parts) + "。",
|
||||
task_type=_classify_task_type(user_query),
|
||||
execution_mode=execution_mode,
|
||||
primary_agent=primary_agent,
|
||||
verification_status=verification_status,
|
||||
verification_summary=state.get("verification_summary"),
|
||||
used_skill_names=used_skill_names,
|
||||
evidence_refs=verification_evidence,
|
||||
task_refs=task_refs,
|
||||
event_refs=event_refs,
|
||||
context_snapshot={
|
||||
"runtime_request_context": runtime_context,
|
||||
"recommended_runtime_mode": runtime_context.get("recommended_runtime_mode"),
|
||||
"parallel_worthiness": state.get("parallel_worthiness"),
|
||||
"retrospective_shortlist_count": len(retrospective_shortlist),
|
||||
"scheduled_subtask_count": len(state.get("scheduled_subtasks") or []),
|
||||
"merge_report": dict(state.get("merge_report") or {}),
|
||||
"verification_report": dict(state.get("verification_report") or {}),
|
||||
},
|
||||
outcome=outcome,
|
||||
)
|
||||
Reference in New Issue
Block a user