You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5.4 KiB

02 知识点地图

每个知识点都绑到源码。学的时候合上文档,能用自己的话讲出来,才算过关。

A. Agent 核心(必须牢固)

A1. ReAct

  • 概念Thought → Action → Observation 循环,直到模型不再调工具
  • 源码:qoze_code_agent.pyllm_call / tool_node / should_continue
  • 过关标准:不看代码画出状态图;能解释“为什么 tool 之后必须再进 llm_call”

A2. LangGraph StateGraph

  • 概念:节点函数返回要更新的 state 字段,不是替换整个对象
  • messages: Annotated[list, operator.add] 表示每次 append
  • compile(checkpointer=...) 让同一 thread_id 能恢复对话
  • 源码:MessagesStateagent_builderinit_agent()
  • 过关标准:自己用 30 行写出同等的两节点图

A3. Tool CallingFunction Calling

  • 概念:模型不直接“执行 Python”它只输出 tool_calls JSON运行时按名字找到函数再跑
  • LangChain@tool 从类型注解和 docstring 生成 schemallm.bind_tools(tools)
  • 源码:tools/*.py@tooltool_nodetools_by_name[name].ainvoke(args)
  • 过关标准:自己写一个 read_file 工具,让模型真的读到磁盘内容

A4. 消息协议

必须分清四种消息,否则 400 错误会搞很久:

类型 谁产生 作用
SystemMessage 角色与规则
HumanMessage 用户 任务
AIMessage 模型 回复或 tool_calls
ToolMessage 你的运行时 把工具结果交回,必须带 tool_call_id

源码:_repair_incomplete_tool_calls

A5. Prompt Caching 拆分

  • 静态放 System动态放 User 前缀
  • 源码:utils/system_prompt.pyget_static_system_prompt / get_dynamic_context
  • 过关标准:能说出“目录树为什么不能放进 SystemMessage”

B. 模型接入(结合你现在的环境)

B1. OpenAI 兼容协议

  • base_url + api_key + model 三件套
  • 你已经在用 https://api.agicto.cn/v1 + DeepSeek
  • 源码:model_initializer.pyChatOpenAI(...)
  • 过关标准10 行脚本能 ainvoke 通;再 bind_tools

B2. 推理模型的 thinking

  • DeepSeek 一类会在 delta 里带 reasoning_content
  • 源码:model_initializer.patch_langchain_openai
  • TUIThinkingWidget
  • 过关标准:知道 thinking 不是最终答案,不要当 assistant content 存

B3. 多厂商适配

  • 这是 Qoze 变复杂的主因Vertex、Kimi、智谱、Qwen 各写一套
  • 改写建议:第一版只保留 OpenAI 兼容 一个适配器

C. 工具与安全

C1. 文件工具

  • 源码:tools/file_tools.py
  • 要点:路径限制在 cwd读文件带行号范围改文件用精确替换而不是整文件覆盖
  • 过关标准:能讲清为什么 write_file 危险、replace_in_file 更稳

C2. Shell 工具

  • 源码:tools/execute_command_tool.py
  • 要点:create_subprocess_shell、超时、stdout/stderr 合并
  • 风险:模型可以 rm -rf / 删盘;改写时要加白名单或人工确认

C3. 并行 tool_calls

  • 一轮里模型可能同时调多个工具
  • 源码:asyncio.gather in tool_node
  • 过关标准:知道“读两个文件可以并行,写同一文件不能瞎并行”

D. 工程结构(决定你改写时像不像业余)

D1. 配置与密钥

  • 源码:config_manager.pyWindows 在 %APPDATA%\qoze\qoze.conf
  • 原则:密钥不进仓库

D2. Checkpoint / 会话

  • SQLite + thread_id
  • /clear 会换新 uuid 并清库
  • 源码:init_agent / save_thread_id / qoze_tui.pyclear

D3. 规则注入

  • .qoze/rules/*.md 每次动态塞进 prompt
  • 这就是 Cursor 的 .cursor/rules 同类机制,非常值得学

E. 插件三件套理解即可MVP 不做)

E1. Skills

  • 发现路径:项目 .qoze/skills > 用户 ~/.qoze/skills > 内置
  • 激活后把 SKILL.md 正文注入动态上下文
  • 源码:skills/skill_manager.py

E2. MCP

  • 配置里写 command + argsstdio 拉起外部 server
  • 激活后 get_active_tools() 合并进 tools_by_name
  • 源码:qoze_mcp/mcp_manager.pytools/mcp_tools.py

E3. Subagent

  • 再 compile 一张无 checkpointer 的图
  • 工具子集,禁止再 dispatch避免套娃
  • 源码:tools/subagent_tool.py_build_subagent

F. TUI体验层可后置

概念 源码 你要懂什么
Textual App qoze_tui.pyclass Qoze(App) compose / 事件 / 异步任务
流式增量 display_buffer.py + stream_scheduler.py 不要每个 token 都 refresh
思考区 thinking_widget.py 和正文拆开
终端兼容 terminal_compat.py Windows GBK / 旧终端会炸 Unicode

Windows 坑你已经踩过Rich 默认 legacy_windows 会 GBK 编码失败。自己项目一开始就 PYTHONUTF8=1TUI 用 Windows Terminal。

G. 建议的练习题(每题半天到一天)

  1. 不用 LangGraph手写一个 while 循环 ReActmessages 列表自己维护)
  2. 用 LangGraph 把上面的循环换成两节点图
  3. 给图加上 read_file + execute_command,完成“读 README 并总结”
  4. 给图加上 SQLite checkpointer重启进程还能续聊
  5. astream 的 token 打到终端(先 print再考虑 Textual
  6. 实现一个 skill激活后模型会按你的 Java 代码规范改代码
  7. 实现一个危险命令拦截:execute_command 前打印 diff/命令并等 y/N