Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

一个面向软件仓库的工程变更分析与故障诊断 Agent。它把架构文档、PR 说明、日志、Runbook 和评测结果组织成可检索证据,并围绕变更影响、PR 风险、故障假设、验证计划和回滚步骤给出有边界的工程结论。

系统核心不是普通问答,而是一条可规划、可执行、可验证、可学习的 Agent 控制流:外层 State Graph 管理流程边界,内层 Plan → Action → Observation → Reflection 负责动态工具决策;Verification Loop 在证据不足时有界重试,并保留断点、继续、编辑后重跑与终止能力。
系统核心不是普通问答,而是一条可规划、可执行、可验证、可学习的 Agent 控制流:外层由 **LangGraph StateGraph** 管理流程边界、条件路由与 Checkpoint,内层 Plan → Action → Observation → Reflection 负责动态工具决策;Verification Loop 在证据不足时有界重试,并保留断点、继续、编辑后重跑与终止能力。

## 主要能力

Expand All @@ -15,6 +15,7 @@
- **生产安全边界**:写操作进入 Human Approval Gate;Tool Registry 提供 idempotency key、执行状态与补偿 rollback 回调,避免重复副作用。
- **证据门控**:检查原问题与命中材料是否有直接领域信号;低证据时不调用外部 LLM。
- **有界恢复**:Query Rewrite、检索预算和全局图转换上限共同防止无界循环。
- **LangGraph 原生编排**:9 个业务节点直接注册到 LangGraph,条件边负责证据重试与 ReAct 循环,`InMemorySaver` + `interrupt/Command` 负责断点和恢复,不再维护第二套自研图执行器。
- **执行轨迹**:Graph Path、Tool Trace、检索次数、实际 Reranker、证据质量和停止原因均可观察。
- **实时运行事件**:`/api/ask/stream` 通过 SSE 在节点完成时推送 Route、Retrieve、Tool、Reflection 与 Final 事件,而不是等整次请求结束后一次性返回。
- **可视化调试**:节点断点、内存 Checkpoint、继续、编辑查询后从 Route 重启、终止与清理。
Expand Down Expand Up @@ -53,7 +54,7 @@ Debug: breakpoint → checkpoint → resume / edit and restart / cancel

- Backend:Python、FastAPI、Pydantic、Uvicorn
- Retrieval:SentenceTransformers、BGE、Dense Cosine Search、Chroma、Cross-Encoder
- Agent:State Graph、ReAct、Planning / Reflection、Verification Loop、Skill、Native/MCP Tool Registry
- Agent:LangGraph、StateGraph、Checkpoint / Interrupt、ReAct、Planning / Reflection、Verification Loop、Skill、Native/MCP Tool Registry
- Memory:Working、Episodic、Semantic、Procedural、幂等 Memory Import
- Safety:Human Approval、Idempotency、Rollback、Bounded Retry / Stop Reason
- LLM:OpenAI-compatible Chat API Adapter(可选)
Expand Down Expand Up @@ -148,7 +149,7 @@ POST /api/debug/resume
DELETE /api/debug/runs/{run_id}
```

`/api/ask` 返回 `answer`、`intent`、`citations`、`trace` 和 `metrics`。调试接口在节点执行前暂停并保留 Checkpoint;完成或取消后清理。
`/api/ask` 返回 `answer`、`intent`、`citations`、`trace` 和 `metrics`;`/api/workflow` 会明确返回 `framework=langgraph`。调试接口通过 LangGraph interrupt 在节点执行前暂停并保留 Checkpoint,使用相同 thread 恢复;完成或取消后清理。

## 测试与评估

Expand Down
16 changes: 14 additions & 2 deletions app/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,9 @@ def __init__(self, kb: KnowledgeBase) -> None:

def workflow_spec(self) -> dict[str, Any]:
return {
"framework": self.workflow.framework,
"checkpointing": "langgraph_in_memory",
"interrupts": "langgraph_dynamic",
"entrypoint": "route",
"nodes": [
"route",
Expand Down Expand Up @@ -374,7 +377,9 @@ def ask(
sid = self.memory.ensure(session_id)
state = self._new_state(query, sid, top_k)
graph_run = self.workflow.run(state, event_sink=event_sink)
return self._build_response(sid, state, graph_run, started, record_memory=True)
response = self._build_response(sid, state, graph_run, started, record_memory=True)
self.workflow.cancel(graph_run.thread_id)
return response

def debug_start(
self,
Expand Down Expand Up @@ -419,6 +424,7 @@ def debug_resume(
next_query = (query or checkpoint.query).strip()

if restart:
self.workflow.cancel(checkpoint.run.thread_id)
state = self._new_state(next_query, checkpoint.session_id, checkpoint.top_k)
state.trace.append(
ToolCall(
Expand All @@ -440,6 +446,7 @@ def debug_resume(
prior_events=checkpoint.run.events,
breakpoints=active_breakpoints,
skip_breakpoint_once=checkpoint.run.next_node,
thread_id=checkpoint.run.thread_id,
)

return self._finish_debug_step(
Expand All @@ -455,7 +462,11 @@ def debug_resume(

def cancel_debug(self, run_id: str) -> bool:
with self._debug_lock:
return self._debug_runs.pop(run_id, None) is not None
checkpoint = self._debug_runs.pop(run_id, None)
if checkpoint is None:
return False
self.workflow.cancel(checkpoint.run.thread_id)
return True

def _new_state(self, query: str, session_id: str, top_k: int) -> AgentState:
normalized_query = self._resolve_follow_up(query, session_id)
Expand Down Expand Up @@ -495,6 +506,7 @@ def _finish_debug_step(
record_memory=completed,
)
if completed:
self.workflow.cancel(graph_run.thread_id)
with self._debug_lock:
self._debug_runs.pop(run_id, None)
else:
Expand Down
98 changes: 0 additions & 98 deletions app/langgraph_adapter.py

This file was deleted.

40 changes: 0 additions & 40 deletions app/langgraph_bridge.py

This file was deleted.

77 changes: 0 additions & 77 deletions app/langgraph_entrypoint.py

This file was deleted.

74 changes: 0 additions & 74 deletions app/langgraph_runtime.py

This file was deleted.

Loading