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
5.4 KiB
02 知识点地图
每个知识点都绑到源码。学的时候合上文档,能用自己的话讲出来,才算过关。
A. Agent 核心(必须牢固)
A1. ReAct
- 概念:Thought → Action → Observation 循环,直到模型不再调工具
- 源码:
qoze_code_agent.py的llm_call/tool_node/should_continue - 过关标准:不看代码画出状态图;能解释“为什么 tool 之后必须再进 llm_call”
A2. LangGraph StateGraph
- 概念:节点函数返回要更新的 state 字段,不是替换整个对象
messages: Annotated[list, operator.add]表示每次 appendcompile(checkpointer=...)让同一thread_id能恢复对话- 源码:
MessagesState、agent_builder、init_agent() - 过关标准:自己用 30 行写出同等的两节点图
A3. Tool Calling(Function Calling)
- 概念:模型不直接“执行 Python”,它只输出
tool_callsJSON;运行时按名字找到函数再跑 - LangChain:
@tool从类型注解和 docstring 生成 schema;llm.bind_tools(tools) - 源码:
tools/*.py的@tool;tool_node里tools_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.py的get_static_system_prompt/get_dynamic_context - 过关标准:能说出“目录树为什么不能放进 SystemMessage”
B. 模型接入(结合你现在的环境)
B1. OpenAI 兼容协议
base_url+api_key+model三件套- 你已经在用
https://api.agicto.cn/v1+ DeepSeek - 源码:
model_initializer.py的ChatOpenAI(...) - 过关标准:10 行脚本能
ainvoke通;再bind_tools通
B2. 推理模型的 thinking
- DeepSeek 一类会在 delta 里带
reasoning_content - 源码:
model_initializer.patch_langchain_openai - TUI:
ThinkingWidget - 过关标准:知道 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.gatherintool_node - 过关标准:知道“读两个文件可以并行,写同一文件不能瞎并行”
D. 工程结构(决定你改写时像不像业余)
D1. 配置与密钥
- 源码:
config_manager.py,Windows 在%APPDATA%\qoze\qoze.conf - 原则:密钥不进仓库
D2. Checkpoint / 会话
- SQLite +
thread_id /clear会换新 uuid 并清库- 源码:
init_agent/save_thread_id/qoze_tui.py的clear
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 + args,stdio 拉起外部 server - 激活后
get_active_tools()合并进tools_by_name - 源码:
qoze_mcp/mcp_manager.py、tools/mcp_tools.py
E3. Subagent
- 再 compile 一张无 checkpointer 的图
- 工具子集,禁止再 dispatch,避免套娃
- 源码:
tools/subagent_tool.py的_build_subagent
F. TUI(体验层,可后置)
| 概念 | 源码 | 你要懂什么 |
|---|---|---|
| Textual App | qoze_tui.py 的 class 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=1,TUI 用 Windows Terminal。
G. 建议的练习题(每题半天到一天)
- 不用 LangGraph,手写一个 while 循环 ReAct(messages 列表自己维护)
- 用 LangGraph 把上面的循环换成两节点图
- 给图加上
read_file+execute_command,完成“读 README 并总结” - 给图加上 SQLite checkpointer,重启进程还能续聊
- 把
astream的 token 打到终端(先 print,再考虑 Textual) - 实现一个 skill:激活后模型会按你的 Java 代码规范改代码
- 实现一个危险命令拦截:
execute_command前打印 diff/命令并等 y/N