@eoasmxd/freya 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/README.md +9 -3
  2. package/core/dist/command/commands/skill-commands.js +5 -4
  3. package/core/dist/config/config-manager.d.ts +5 -1
  4. package/core/dist/config/config-manager.js +13 -1
  5. package/core/dist/kernel.js +2 -2
  6. package/core/dist/skill/skill-registry.d.ts +12 -2
  7. package/core/dist/skill/skill-registry.js +89 -8
  8. package/core/dist/tools/meta/index.d.ts +3 -1
  9. package/core/dist/tools/meta/index.js +9 -1
  10. package/core/dist/web/config-api.js +18 -0
  11. package/core/package.json +2 -2
  12. package/doc/_index.md +20 -7
  13. package/doc/getting-started.md +1 -1
  14. package/doc/installation-guide.md +2 -2
  15. package/doc/{architecture-design.md → specifications/architecture-design.md} +7 -4
  16. package/doc/{config-spec.md → specifications/config-spec.md} +1 -1
  17. package/doc/{llm-interface-params.md → specifications/llm-interface-params.md} +8 -8
  18. package/doc/{prompt-system.md → specifications/prompt-system.md} +1 -1
  19. package/doc/tutorials/_index.md +96 -0
  20. package/doc/tutorials/part0_basic/0.1_probability_prediction.md +155 -0
  21. package/doc/tutorials/part0_basic/0.2_attention_and_context.md +145 -0
  22. package/doc/tutorials/part0_basic/0.3_generation_parameters.md +132 -0
  23. package/doc/tutorials/part0_basic/0.4_debugging_token.md +99 -0
  24. package/doc/tutorials/part0_basic/1.1_stateless_and_history.md +143 -0
  25. package/doc/tutorials/part0_basic/1.2_chat_data_structure.md +179 -0
  26. package/doc/tutorials/part0_basic/1.3_system_user_assistant.md +147 -0
  27. package/doc/tutorials/part0_basic/1.4_freya_model_proxy.md +203 -0
  28. package/doc/tutorials/part0_basic/_index.md +28 -0
  29. package/doc/tutorials/part1_react/2.1_agency_vs_chatbot.md +127 -0
  30. package/doc/tutorials/part1_react/2.2_react_mind_model.md +144 -0
  31. package/doc/tutorials/part1_react/2.3_freya_agent_executor.md +233 -0
  32. package/doc/tutorials/part1_react/2.4_debugging_loop_deadlock.md +160 -0
  33. package/doc/tutorials/part1_react/3.1_hardcoded_prompt_pain.md +104 -0
  34. package/doc/tutorials/part1_react/3.2_decoupled_architecture.md +138 -0
  35. package/doc/tutorials/part1_react/3.3_freya_dual_read_probe.md +152 -0
  36. package/doc/tutorials/part1_react/3.4_debugging_composition_placeholder.md +97 -0
  37. package/doc/tutorials/part1_react/_index.md +28 -0
  38. package/doc/tutorials/part2_tools/4.1_json_schema_mapping.md +119 -0
  39. package/doc/tutorials/part2_tools/4.2_tool_call_raw_packet.md +105 -0
  40. package/doc/tutorials/part2_tools/4.3_freya_tool_execution.md +145 -0
  41. package/doc/tutorials/part2_tools/4.4_debugging_observation_fix.md +154 -0
  42. package/doc/tutorials/part2_tools/5.1_observation_injection.md +131 -0
  43. package/doc/tutorials/part2_tools/5.2_openai_vs_gemini_protocol.md +125 -0
  44. package/doc/tutorials/part2_tools/5.3_freya_llm_proxy_mapping.md +162 -0
  45. package/doc/tutorials/part2_tools/5.4_debugging_parallel_call_chaos.md +135 -0
  46. package/doc/tutorials/part2_tools/_index.md +28 -0
  47. package/doc/tutorials/part3_memory/6.1_session_state_lifecycle.md +143 -0
  48. package/doc/tutorials/part3_memory/6.2_physical_sandbox_separation.md +108 -0
  49. package/doc/tutorials/part3_memory/6.3_freya_session_storage.md +139 -0
  50. package/doc/tutorials/part3_memory/6.4_debugging_session_concurrency.md +161 -0
  51. package/doc/tutorials/part3_memory/7.1_context_overflow_loss.md +109 -0
  52. package/doc/tutorials/part3_memory/7.2_sliding_window_vs_summary.md +85 -0
  53. package/doc/tutorials/part3_memory/7.3_freya_compactor_impl.md +142 -0
  54. package/doc/tutorials/part3_memory/7.4_debugging_summarize_deadlock.md +160 -0
  55. package/doc/tutorials/part3_memory/_index.md +28 -0
  56. package/doc/tutorials/part4_streaming/8.1_sse_protocol_basics.md +119 -0
  57. package/doc/tutorials/part4_streaming/8.2_hiding_thoughts_in_stream.md +132 -0
  58. package/doc/tutorials/part4_streaming/8.3_freya_event_bus.md +104 -0
  59. package/doc/tutorials/part4_streaming/8.4_debugging_stream_decoder.md +158 -0
  60. package/doc/tutorials/part4_streaming/9.1_abort_signal_braking.md +162 -0
  61. package/doc/tutorials/part4_streaming/9.2_async_event_channels.md +142 -0
  62. package/doc/tutorials/part4_streaming/9.3_freya_abort_billing.md +122 -0
  63. package/doc/tutorials/part4_streaming/9.4_debugging_abort_lock_deadlock.md +187 -0
  64. package/doc/tutorials/part4_streaming/_index.md +28 -0
  65. package/doc/tutorials/part5_plugins/10.1_microkernel_decoupling.md +142 -0
  66. package/doc/tutorials/part5_plugins/10.2_plugin_metadata_security.md +125 -0
  67. package/doc/tutorials/part5_plugins/10.3_channel_plugin_development.md +149 -0
  68. package/doc/tutorials/part5_plugins/10.4_debugging_channel_reconnection.md +160 -0
  69. package/doc/tutorials/part5_plugins/_index.md +21 -0
  70. package/doc/tutorials/part6_advanced/11.1_react_model_flaws.md +111 -0
  71. package/doc/tutorials/part6_advanced/11.2_reflexion_mind_model.md +103 -0
  72. package/doc/tutorials/part6_advanced/11.3_reflexion_hands_on.md +182 -0
  73. package/doc/tutorials/part6_advanced/11.4_debugging_reflexion_convergence.md +108 -0
  74. package/doc/tutorials/part6_advanced/12.1_single_agent_limits.md +100 -0
  75. package/doc/tutorials/part6_advanced/12.2_multi_agent_patterns.md +121 -0
  76. package/doc/tutorials/part6_advanced/12.3_freya_multi_agent_routing.md +143 -0
  77. package/doc/tutorials/part6_advanced/12.4_multi_agent_hands_on.md +176 -0
  78. package/doc/tutorials/part6_advanced/_index.md +28 -0
  79. package/doc/tutorials/preface.md +30 -0
  80. package/package.json +3 -2
  81. package/plugins/plugin-gemini/package.json +1 -1
  82. package/plugins/plugin-openai/package.json +1 -1
  83. package/plugins/plugin-telegram-channel/package.json +1 -1
  84. package/plugins/plugin-tool-fs/package.json +1 -1
  85. package/plugins/plugin-tool-memory/package.json +1 -1
  86. package/plugins/plugin-tool-mysql/config/prompts/plugin.prompt.mysql.md +9 -0
  87. package/plugins/plugin-tool-mysql/config/prompts/plugin.prompt.mysql.select.audit.md +26 -0
  88. package/plugins/plugin-tool-mysql/dist/audit.d.ts +13 -0
  89. package/plugins/plugin-tool-mysql/dist/audit.js +87 -0
  90. package/plugins/plugin-tool-mysql/dist/index.d.ts +14 -0
  91. package/plugins/plugin-tool-mysql/dist/index.js +34 -0
  92. package/plugins/plugin-tool-mysql/dist/pool-manager.d.ts +32 -0
  93. package/plugins/plugin-tool-mysql/dist/pool-manager.js +113 -0
  94. package/plugins/plugin-tool-mysql/dist/tools.d.ts +11 -0
  95. package/plugins/plugin-tool-mysql/dist/tools.js +88 -0
  96. package/plugins/plugin-tool-mysql/package.json +33 -0
  97. package/plugins/plugin-tool-mysql/schema.json +83 -0
  98. package/plugins/plugin-tool-web/package.json +1 -1
  99. package/plugins/plugin-wecom-channel/package.json +1 -1
  100. package/plugins/plugin-weixin-channel/package.json +1 -1
  101. package/src/packages/core/src/command/commands/skill-commands.ts +6 -5
  102. package/src/packages/core/src/config/config-manager.ts +15 -1
  103. package/src/packages/core/src/kernel.ts +3 -2
  104. package/src/packages/core/src/skill/skill-registry.ts +100 -8
  105. package/src/packages/core/src/tools/meta/index.ts +9 -1
  106. package/src/packages/core/src/web/config-api.ts +20 -0
  107. package/src/packages/ui/src/features/config/ConfigModal.tsx +13 -1
  108. package/src/packages/ui/src/features/config/panels/SkillConfigPanel.tsx +137 -0
  109. package/src/plugins/plugin-tool-mysql/src/audit.ts +103 -0
  110. package/src/plugins/plugin-tool-mysql/src/index.ts +44 -0
  111. package/src/plugins/plugin-tool-mysql/src/pool-manager.ts +132 -0
  112. package/src/plugins/plugin-tool-mysql/src/tools.ts +100 -0
  113. package/ui/assets/{index-Be0cAgdB.js → index-BqPQMflk.js} +14 -14
  114. package/ui/index.html +1 -1
@@ -0,0 +1,96 @@
1
+ ---
2
+ title: "智能体通用原理与开发实战"
3
+ linkTitle: "首页"
4
+ weight: 1
5
+ ---
6
+
7
+ # 智能体通用原理与开发实战
8
+
9
+ 欢迎来到《智能体通用原理与开发实战》教程!
10
+
11
+ ## 🎯 教程定位
12
+
13
+ 本教程完全以 **AI Agent(智能体)的通用底层原理、通信协议与架构机制**为主线,将 Freya 定位为学员透视这些机制的“透明白盒沙箱”,提供平缓的学习曲线和丰富的动手实验。
14
+
15
+ 本教程拒绝浮于表面的概念科普,采用高密度的深度硬核写作风格。全书包含 13 个完整章节,力求做到“底层原理讲透、白盒源码剖析清晰、一线避坑指南实用”,为您拼全智能体开发的底层心智与工程拼图。
16
+
17
+ ## 🗺️ 课程自学通关路线图
18
+
19
+ ### 📦 [第零部分:AI 基础概念与“文字接龙”的秘密](part0_basic/_index.md)
20
+ * **第 0 章:揭开 AI 的神秘面纱 —— 大语言模型运作本质**
21
+ * [0.1 概率预测与 Next-Token Prediction](part0_basic/0.1_probability_prediction.md) —— *自回归大模型与 Token 切分、计费的底层秘密*
22
+ * [0.2 算力与窗口的物理极限](part0_basic/0.2_attention_and_context.md) —— *Attention 机制平方复杂度与 KV Cache 显存深渊*
23
+ * [0.3 随机与严谨的博弈](part0_basic/0.3_generation_parameters.md) —— *Temperature, Top-P 等采样参数的数学物理本质*
24
+ * [0.4 调试与避坑指南:本地 Token 消耗排查](part0_basic/0.4_debugging_token.md) —— *中英文混淆、JSON 格式 Token 刺客与 API 限流估算*
25
+ * **第 1 章:对话的舞台 —— 大模型聊天接口与三种角色**
26
+ * [1.1 鱼的记忆与无状态网络](part0_basic/1.1_stateless_and_history.md) —— *网络无状态本质与多轮会话拼接的底层逻辑*
27
+ * [1.2 聊天数据结构解析](part0_basic/1.2_chat_data_structure.md) —— *API 请求与响应 Message/Response 物理格式解析*
28
+ * [1.3 三大核心角色分工](part0_basic/1.3_system_user_assistant.md) —— *System/User/Assistant 三大角色分工、Prefilling 与注入防御*
29
+ * [1.4 【沙箱对照】阅读与调试模型代理配置](part0_basic/1.4_freya_model_proxy.md) —— *底座统一代理配置与异构参数清洗抹平*
30
+
31
+ ### 🧠 [第一部分:Agent 的心智模型 —— 探秘 ReAct 决策环与沙箱物理隔离](part1_react/_index.md)
32
+ * **第 2 章:智能体架构演进 —— 从聊天助手到能动的主体**
33
+ * [2.1 能动性(Agency)的诞生](part1_react/2.1_agency_vs_chatbot.md) —— *Chatbot 与 Agent 控制流革命及四大物理要素*
34
+ * [2.2 ReAct 心智模型与推演](part1_react/2.2_react_mind_model.md) —— *Thought-Action-Observation 三元环时序与 Prompt 模板*
35
+ * [2.3 【白盒剖析】决策循环与 agent-executor 源码](part1_react/2.3_freya_agent_executor.md) —— *主循环控制流与闲置工具箱动态淘汰算法*
36
+ * [2.4 调试与避坑指南:ReAct 自循环失控熔断](part1_react/2.4_debugging_loop_deadlock.md) —— *动手实验复现鬼打墙及内核防爆网设计*
37
+ * **第 3 章:系统提示词的动态织造与零硬编码规范**
38
+ * [3.1 提示词工程的痛点](part1_react/3.1_hardcoded_prompt_pain.md) —— *硬编码提示词的四大工程灾难与解耦世界观*
39
+ * [3.2 零硬编码解耦架构](part1_react/3.2_decoupled_architecture.md) —— *零硬编码物理目录树规范与热加载双缓冲原子替换*
40
+ * [3.3 【白盒剖析】双通道动态提示词合并](part1_react/3.3_freya_dual_read_probe.md) —— *双通道探针内存编织与 composeSystemPrompt 运行时插值*
41
+ * [3.4 调试与避坑指南:动态 Prompt 拼装与模板报错排查](part1_react/3.4_debugging_composition_placeholder.md) —— *占位符解析失效、Prompt 捕获探针及安全模板替换器*
42
+
43
+ ### 🔌 [第二部分:连接物理世界 —— 智能体如何掌控“工具” (Tool Call)](part2_tools/_index.md)
44
+ * **第 4 章:大模型感知与选择工具的底层技术本质**
45
+ * [4.1 语言到动作的转换](part2_tools/4.1_json_schema_mapping.md) —— *JSON Schema 描述符、受约束生成与高质量 Description 准则*
46
+ * [4.2 【白盒剖析】Tool Call Raw 数据包结构](part2_tools/4.2_tool_call_raw_packet.md) —— *非流式 JSON 标本、流式 arguments 拼接与并行调用风暴*
47
+ * [4.3 【白盒剖析】工具安全防线与本地执行](part2_tools/4.3_freya_tool_execution.md) —— *FreyaToolRegistry 结构、动态过滤授权沙箱与 EventBus 状态流转*
48
+ * [4.4 调试与避坑指南:错误 Observation 与自我修正](part2_tools/4.4_debugging_observation_fix.md) —— *引导性错误 Observation 纠错、堆栈过滤与海量数据截断*
49
+ * **第 5 章:大厂 Function Calling 协议差异与多轮关联流派**
50
+ * [5.1 工具执行结果的归流](part2_tools/5.1_observation_injection.md) —— *反向注入注意力时序重建与 tool_calls 消息保留红线*
51
+ * [5.2 两大厂商协议流派交锋](part2_tools/5.2_openai_vs_gemini_protocol.md) —— *OpenAI 显式 call_id 强关联 vs Gemini 函数名隐式关联*
52
+ * [5.3 【白盒剖析】Freya 大模型代理层协议映射](part2_tools/5.3_freya_llm_proxy_mapping.md) —— *LLM 统一代理与插件契约、通用消息与各厂商原生请求体转换*
53
+ * [5.4 调试与避坑指南:并发多工具调用关联混乱排错](part2_tools/5.4_debugging_parallel_call_chaos.md) —— *并发工具调用乱序报错复现、时序重组与局部崩溃隔离*
54
+
55
+ ### 💾 [第三部分:大脑的心流与记忆机制 —— 会话与上下文管理](part3_memory/_index.md)
56
+ * **第 6 章:智能体的短期记忆、多轮会话与持久化安全隔离**
57
+ * [6.1 会话管理生命周期与数据结构](part3_memory/6.1_session_state_lifecycle.md) —— *会话物理生命周期、Session 数据结构与 LRU 缓存设计*
58
+ * [6.2 【沙箱设计】数据与源码物理隔离](part3_memory/6.2_physical_sandbox_separation.md) —— *混合存储物理灾难、Freya 运行时物理沙箱隔离划分与初始化*
59
+ * [6.3 【白盒剖析】物理持久化存储机制](part3_memory/6.3_freya_session_storage.md) —— *优化吞吐延迟加载、并发更新排队锁与异步压缩调度*
60
+ * [6.4 调试与避坑指南:高并发会话串线与写入锁排查](part3_memory/6.4_debugging_session_concurrency.md) —— *异步模型下 Session 串线复现、AsyncLocalStorage 隔离与磁盘写冲突文件锁*
61
+ * **第 7 章:上下文窗口溢出危机:压缩、滚动与摘要算法**
62
+ * [7.1 上下文溢出的毁灭性后果与窗口危机](part3_memory/7.1_context_overflow_loss.md) —— *溢出崩溃路径、静默截断三大灾难与量化模型窗口缩减陷阱*
63
+ * [7.2 上下文压缩机制:滑动窗口与递归摘要算法](part3_memory/7.2_sliding_window_vs_summary.md) —— *滑动窗口淘汰、主动递归摘要与时序失真的摘要模板防御*
64
+ * [7.3 【白盒剖析】Compactor 与淘汰算法](part3_memory/7.3_freya_compactor_impl.md) —— *双轨压缩判定、安全截断点回溯算法与轻量正则 Token 预估*
65
+ * [7.4 调试与避坑指南:递归摘要“套娃死锁”防御](part3_memory/7.4_debugging_summarize_deadlock.md) —— *套娃死锁触发与复现、硬性计数闸与摘要 Token 边界保护*
66
+
67
+ ### ⚡ [第四部分:智能体的血脉与交互体验 —— 流式通信与事件驱动](part4_streaming/_index.md)
68
+ * **第 8 章:用户交互期望:流式响应 (Streaming Delta) 的传输秘密**
69
+ * [8.1 SSE 协议本质与首字延迟革命](part4_streaming/8.1_sse_protocol_basics.md) —— *首字延迟 (TTFT) 交互革命、SSE 单向长连接抓包与 Nginx 憋尿效应防范*
70
+ * [8.2 隐藏中间推理的工程艺术](part4_streaming/8.2_hiding_thoughts_in_stream.md) —— *双轨管道过滤、隐藏推理流实现与切碎 XML 标签防范*
71
+ * [8.3 【白盒剖析】EventBus 事件广播与响应推送](part4_streaming/8.3_freya_event_bus.md) —— *EventBus 广播 reply 信号机制与事件重播缓冲区机制*
72
+ * [8.4 调试与避坑指南:反代缓存与流式 UTF-8 字符截断排错](part4_streaming/8.4_debugging_stream_decoder.md) —— *TCP 分片与 UTF-8 半字截断、StringDecoder 妙用与流式 JSON 稳定提取*
73
+ * **第 9 章:计费解耦、状态监测与异步中断 (Abort)**
74
+ * [9.1 链路级刹车机制](part4_streaming/9.1_abort_signal_braking.md) —— *AbortSignal 刹车拉线、底座多路刹车分发与 TCP Leak 僵尸连接防范*
75
+ * [9.2 异步事件通信机制](part4_streaming/9.2_async_event_channels.md) —— *三层事件解耦架构、微信通道事件流转与监听器内存泄露*
76
+ * [9.3 【白盒剖析】中断流转与抢救性结算](part4_streaming/9.3_freya_abort_billing.md) —— *中断生命周期控制链、部分响应抢救落盘与父子智能体异步级联刹车*
77
+ * [9.4 调试与避坑指南:中断抢占死锁与句柄释放排查](part4_streaming/9.4_debugging_abort_lock_deadlock.md) —— *中断抢占 Pending Deadlock 死锁复现、finally 释放防线与状态机通道复位*
78
+
79
+ ### 📱 [第五部分:触达物理世界 —— 微内核、插件契约与通道适配](part5_plugins/_index.md)
80
+ * **第 10 章:微内核与通道插件的设计哲学:屏蔽 IM 协议差异**
81
+ * [10.1 微内核架构解耦与插件契约设计](part5_plugins/10.1_microkernel_decoupling.md) —— *Core 内核事件分发、Monorepo 依赖边界单向铁律与循环依赖检测*
82
+ * [10.2 依赖边界与安全沙箱](part5_plugins/10.2_plugin_metadata_security.md) —— *静态元数据下沉声明优势、默认关闭零信任安全启停与越权排查*
83
+ * [10.3 【白盒剖析】通道插件开发与消息转换](part5_plugins/10.3_channel_plugin_development.md) —— *Connection ID 物理路由绑定、微信多模态二进制解密与双向事件桥接*
84
+ * [10.4 调试与避坑指南:物理连接假死与指数退避重连](part5_plugins/10.4_debugging_channel_reconnection.md) —— *静默假死成因、复现网络黑洞挂起、超时熔断与指数退避及消息风暴防御*
85
+
86
+ ### 🚀 [第六部分:前沿展望与架构演进 —— 走向更高级的 Agent](part6_advanced/_index.md)
87
+ * **第 11 章:超越 ReAct:自我反思 (Self-Reflection) 与复杂规划 (Planning)**
88
+ * [11.1 ReAct 决策环的物理缺陷](part6_advanced/11.1_react_model_flaws.md) —— *长链路逻辑依赖缺陷、误差累积与高频 Tool Call 重复拦截器*
89
+ * [11.2 进阶反思心智模型解析](part6_advanced/11.2_reflexion_mind_model.md) —— *从挫败中归纳经验、Reflexion 三原色角色分工与反思记忆注入控制*
90
+ * [11.3 动手实验:反射循环开发](part6_advanced/11.3_reflexion_hands_on.md) —— *高难度温度转换器任务设计、编写 Reflexion 闭环控制与 eval 安全防范*
91
+ * [11.4 调试与避坑指南:评估反思开销与收敛成功率](part6_advanced/11.4_debugging_reflexion_convergence.md) —— *Critique Loop 两大物理痛点、反思轨迹追踪器及代码膨胀熔断机制*
92
+ * **第 12 章:从单体走向多智能体协作 (Multi-Agent Systems)**
93
+ * [12.1 独木难支:单 Agent 的能力与认知限界](part6_advanced/12.1_single_agent_limits.md) —— *单体工具爆炸与角色污染、社会化分工及分布式状态死锁防范*
94
+ * [12.2 多智能体协作经典范式](part6_advanced/12.2_multi_agent_patterns.md) —— *集中式 Hub-and-Spoke 星形控制 vs 分布式 P2P 网状对等协作及 Hop Counter*
95
+ * [12.3 【白盒剖析】基于事件总线的多体路由](part6_advanced/12.3_freya_multi_agent_routing.md) —— *SpawnSubagentTool 工具定义、路由指纹与子代生命周期 runSubAgent 接管*
96
+ * [12.4 动手实验与三体协同工作流](part6_advanced/12.4_multi_agent_hands_on.md) —— *三体协同软件交付流水线、Swarms集群展望与全局链路费用熔断闸防范*
@@ -0,0 +1,155 @@
1
+ ---
2
+ title: "0.1 概率预测与 Next-Token Prediction"
3
+ weight: 10
4
+ description: "解密自回归模型的底层概率机制与 Tokenizer 分词原理,剖析中英文 Token 差异对 Agent 开发的物理影响。"
5
+ ---
6
+
7
+ # 0.1 概率预测与 Next-Token Prediction
8
+
9
+ 当我们与各种号称具备“通用人工智能(AGI)”的智能体(Agent)对话时,它们那行云流水、仿佛充满智慧的回答常常让我们产生一种错觉:大语言模型(LLM)正像人类一样在思考。
10
+
11
+ 然而,拉开这层温润的拟人化面纱,智能体的大脑深处其实只在物理性地重复着一个单调而朴素的动作 —— **文字接龙**。
12
+
13
+ ---
14
+
15
+ ## 一、 概率预测与自回归(Autoregressive)机制
16
+
17
+ 大语言模型(LLM)的本质,是一个基于海量文本训练出来的**概率预测概率分布模型**。它的终极任务非常简单:**给定一段已知的上文,预测下一个可能出现的词(或字符)的概率分布**。
18
+
19
+ ### 1. 自回归的物理数学公式
20
+ 在数学上,这一过程被称为**自回归(Autoregressive)**模型。其概率计算公式可以表示为:
21
+
22
+ $$P(w_t \mid w_1, w_2, \dots, w_{t-1})$$
23
+
24
+ 其中:
25
+ * $w_1, w_2, \dots, w_{t-1}$ 代表输入给大模型的历史所有文本(即上下文,Context)。
26
+ * $w_t$ 代表即将生成的第 $t$ 个词。
27
+ * $P$ 则是在给定上述已知历史的条件下,生成 $w_t$ 的概率。
28
+
29
+ 当模型通过这一公式预测出第 $t$ 个词后,会立即将这个新词拼接到原本的输入上,重新作为新的“已知上下文”,再次喂给大模型,去预测第 $t+1$ 个词。这种“左手倒右手、自我回归、循环迭代”的生成机制,就是大模型产生连续文本的底层逻辑。
30
+
31
+ ```
32
+ 已知输入: "今天天气真" ───> 【LLM 大脑】 ───> 预测下一个字概率: {"好": 85%, "晴": 10%, "糟糕": 5%}
33
+
34
+ ▼ (选中 "好")
35
+ 新输入: "今天天气真好" ───> 【LLM 大脑】 ───> 预测下一个字概率: {",": 90%, "。": 8%, "了": 2%}
36
+ ```
37
+
38
+ ### 2. 为什么自回归机制决定了 Agent 的基本形态?
39
+ 这种“Next-Token Prediction(下一个词预测)”的物理局限性,直接决定了 Agent 的两个最底层特性:
40
+ 1. **无状态性(Stateless)**:大模型就像一个函数计算,对于相同的输入和参数,它吐出的概率分布是确定的。它本身是不具备“时间”概念的,每次请求它都记不得上一次你是谁。因此,多轮会话(Session)的记忆完全依赖于我们在客户端源源不断地把历史聊天记录拼接成一个巨大的上下文重新发送。
41
+ 2. **累积误差(Error Accumulation)**:因为第 $t$ 个词的生成依赖第 $t-1$ 个词。一旦大模型在中间某一步预测出了一个逻辑错误的词,这个“错误”就会被当作既定事实重新塞回输入,引发后面的多米诺骨牌效应。这也就是为什么智能体在规划任务时容易陷入“鬼打墙”或中途跑偏的原因。
42
+
43
+ ---
44
+
45
+ ## 二、 什么是 Token 与 Tokenizer 的工作原理
46
+
47
+ 大模型是不能直接看懂“今天天气真好”或者 "Hello World" 这些自然语言字符的。在大模型内部,所有的文字都需要被转化成高维的数学向量(Embeddings)。而在这两者之间起到翻译官作用的,就是 **Tokenizer(分词器)**。
48
+
49
+ ### 1. Token 的定义
50
+ **Token** 是大语言模型处理文本的最小语义单元。一个 Token 可以是一个完整的单词(如 `apple`)、一个词根(如 `un`)、一个单字(如 `好`),甚至可以是一个标点符号,或者一串空格。
51
+
52
+ 大模型在训练前会确定一个**词表(Vocabulary)**,词表里收集了几万到几十万个常用的 Token 单元,每个 Token 都有一个唯一的整数 ID 对应。例如:
53
+ * `"the"` 对应 ID `1824`
54
+ * `"apple"` 对应 ID `7362`
55
+ * `"好"` 对应 ID `32890`
56
+
57
+ ### 2. Byte-Pair Encoding (BPE) 算法机制
58
+ 现代大模型(如 GPT-4, Llama 3)大多使用 **BPE(字节对编码)** 算法来切分 Token。BPE 的核心逻辑是从字节级别开始,通过统计学方法逐步合并高频出现的字符对:
59
+
60
+ 1. **初始化**:将词表初始化为所有基本的字符(如 256 个 ASCII 码或 UTF-8 基础字节)。
61
+ 2. **统计与合并**:扫描训练语料,统计相邻字符对(如 `e` 和 `s`)的出现频次,将最高频的组合合并成一个新的 Token(如 `es`)。
62
+ 3. **循环往复**:重复合并步骤,直到词表大小达到设定阈值(例如 100,000 个 Token)。
63
+
64
+ 通过这种方式,高频单词如 `"the"`、`"and"` 会被合并为一个 Token,而低频词或生僻词(如 `"antigravity"`)则会被拆分为多个 Token(如 `anti` + `gravity`)。这保证了词表既不会无限膨胀,又不会因为遇到生僻词而无法解析。
65
+
66
+ ---
67
+
68
+ ## 三、 中英文 Token 的底层物理差异
69
+
70
+ 作为 Agent 开发者,我们需要深刻意识到中英文在 Tokenize 上的物理差异。这种差异**本质上取决于分词器(Tokenizer)的词表大小与训练语料比例的设计,而非语言或模型能力本身的缺陷**。由于大模型 API 的**上下文限制(Context Window)**和**计费**都是基于 Token 数量而非字符数计算的,因此分词器的设计对 Agent 的研发成本和窗口管理起着决定性作用。
71
+
72
+ ### 不同分词器下的中英文密度差异
73
+
74
+ * **旧世代分词器的设计局限(以 OpenAI `cl100k_base` 为例)**:
75
+ 由于早期的分词器训练语料中英文占比超过 95%,且词表容量较小(如 100k),导致英文的切分效率极高(通常 **1 个 Token 约等于 4 个英文字符**,或者 0.75 个英文单词)。而中文由于紧凑且没有物理空格,大部分汉字无法在词表中合并为词组,甚至部分汉字会因找不到而退化为原始 UTF-8 字节进行解析(在 UTF-8 中 1 个汉字占 3 字节,直接变成 3 个 Token 的惨烈消耗)。
76
+ 在此类分词器下,在表达相同的语义信息量时,中文往往比英文需要多消耗约一倍的 Token 数量,这也影响了会话窗口的留存深度。
77
+
78
+ * **大词表与多语言优化分词器(以 `o200k_base` 及国产模型分词器为例)**:
79
+ 随着词表容量扩充(如 GPT-4o 采用的 200k 词表)以及中文训练语料占比的大幅提升,新一代分词器和国产大模型(如 DeepSeek、Qwen 等)对中文分词效率进行了针对性的深度优化。
80
+ 在这些新型分词器中,大量的中文常用单字和词组被直接收录为单个 Token(1 个汉字平均仅消耗 0.3 到 0.6 个 Token)。在表达相同语义时,中文与英文的 Token 消耗量已基本处于对等状态,甚至在特定的精炼中文表述中,中文的 Token 承载率会比英文更高。
81
+
82
+ 在进行 Agent 架构设计和预算预估时,应当针对所选模型的分词器特性进行实际测试,以获得准确的 Token 消耗模型。
83
+
84
+ ---
85
+
86
+ ## 四、 【代码实验】中英文 Token 密度的物理测量
87
+
88
+ 为了严谨,我们直接用代码在本地测试不同文本的 Token 切分情况,拒绝自我想象。
89
+
90
+ 在 Node.js 环境下,我们可以使用纯 JavaScript 编写的官方分词器 **`js-tiktoken`** 。
91
+
92
+ 在运行本段实验前,您需要先在脚本所在的目录下执行以下命令安装该依赖包:
93
+
94
+ ```bash
95
+ npm install js-tiktoken
96
+ ```
97
+
98
+ ### 1. 实验代码 (token_test.js)
99
+ ```javascript
100
+ const { getEncoding } = require("js-tiktoken");
101
+
102
+ // 初始化 GPT-4 (cl100k_base) 和 GPT-4o (o200k_base) 分词器
103
+ const cl100k = getEncoding("cl100k_base");
104
+ const o200k = getEncoding("o200k_base");
105
+
106
+ const englishText = "Hello, World! Welcome to the world of AI Agents.";
107
+ const chineseText = "你好,世界!欢迎来到智能体的物理世界。";
108
+
109
+ console.log("==================== 1. 英文文本测试 ====================");
110
+ console.log(`文本内容: "${englishText}"`);
111
+ console.log(`字符长度 (Length): ${englishText.length}\n`);
112
+
113
+ const eng100k = cl100k.encode(englishText);
114
+ const eng200k = o200k.encode(englishText);
115
+
116
+ console.log(`[旧版 cl100k_base (GPT-4)] -> Token 数: ${eng100k.length} | 密度比: ${(englishText.length / eng100k.length).toFixed(2)}`);
117
+ console.log(`[新版 o200k_base (GPT-4o)] -> Token 数: ${eng200k.length} | 密度比: ${(englishText.length / eng200k.length).toFixed(2)}\n`);
118
+
119
+ console.log("==================== 2. 中文文本测试 ====================");
120
+ console.log(`文本内容: "${chineseText}"`);
121
+ console.log(`字符长度 (Length): ${chineseText.length}\n`);
122
+
123
+ const ch100k = cl100k.encode(chineseText);
124
+ const ch200k = o200k.encode(chineseText);
125
+
126
+ console.log(`[旧版 cl100k_base (GPT-4)] -> Token 数: ${ch100k.length} | 密度比: ${(chineseText.length / ch100k.length).toFixed(2)}`);
127
+ console.log(`[新版 o200k_base (GPT-4o)] -> Token 数: ${ch200k.length} | 密度比: ${(chineseText.length / ch200k.length).toFixed(2)}`);
128
+ ```
129
+
130
+ 在终端执行以下命令运行该脚本:
131
+
132
+ ```bash
133
+ node token_test.js
134
+ ```
135
+
136
+ ### 2. 测量结果与痛点分析
137
+ 运行上述代码,你将直观地看到:
138
+ * **英文文本表现稳定**:在两代分词器下,英文字符数均为 48 个,切分出的 Token 数量均为 **12 个**(字符/Token 密度比均为 **4.00**),说明词表容量升级对结构成熟的英文文本压缩影响不大。
139
+ * **中文文本优化显著**:中文字符数为 19 个。在旧版 `cl100k_base` 下,由于高频词未合并,切分出多达 **24 个 Token**(密度比仅为 **0.79**);而在新版 `o200k_base` 下,因为常用汉字与词组并入词表,Token 数量暴降至 **13 个**,密度比直接拉升到 **1.46**,降幅达到近 45%。
140
+
141
+ > [!NOTE]
142
+ > 需要注意的是,本实验仅展示了以 OpenAI 模型体系为代表的两代分词器。在实际的 Agent 研发中,不同的模型厂商会使用完全不同的分词器。特别是专门针对中文语料进行深度优化的国产大模型(如 DeepSeek、Qwen 等),其分词器对中文汉字的压缩率通常会更高(一个汉字有时仅消耗 0.3 到 0.5 个 Token)。因此在对接其他厂商的模型时,应当根据其对应分词器的真实表现进行评估。
143
+ >
144
+ > 此外,虽然本教程(Freya 项目)为了便于教学讲解,其内置系统提示词均采用中文编写,但这并不意味着中文提示词在指令遵循和推理性能上优于英文。现阶段对于大多数国际主流基座模型而言,英文提示词在逻辑推理、格式约束和长文本遵循上依然更具优势。在生产环境部署中,建议开发者根据所使用模型的语言偏好,将提示词优化并翻译为英文以追求更佳的性能。
145
+
146
+ ### 3. “Token 刺客”排查防范
147
+ 在 Agent 实际工程中,有以下两个最容易被忽略的“Token 刺客”,它们会在暗中吃掉你的上下文配额:
148
+ 1. **JSON 缩进与冗余字符**:
149
+ 为了方便阅读,我们常常将 API 传递的数据格式化为带有换行和四个空格缩进的 JSON。在大模型眼中,**连续的空格和换行符同样也是 Token**。一个格式化优美的 JSON 数据可能会包含成百上千个无意义的空格 Token。
150
+ * *防御手段*:在喂给大模型前,必须使用 `JSON.stringify(data)` 进行紧凑压缩,抹去所有换行和缩进。
151
+ 2. **Markdown 表格与标点**:
152
+ 复杂的表格边框符号(如 `|`、`-`)会产生高频碎片 Token。
153
+ * *防御手段*:非必要时不传大量原始表格数据,可以转换为更紧凑的 CSV 格式或简明文本列表送入。
154
+
155
+ 通过本节的物理剖析,你应该明白:**大模型是用概率在“接龙”,而它的世界尺度是 Token。** 建立起这个物理认知,是我们后续开发任何高内聚 Agent 架构(如 ReAct、记忆池)的重要逻辑基石。
@@ -0,0 +1,145 @@
1
+ ---
2
+ title: "0.2 算力与窗口的物理极限"
3
+ weight: 20
4
+ description: "解剖自注意力机制的平方复杂度与 KV Cache 显存占用,透视 Context Window 的硬件瓶颈与 Lost in the Middle 现象。"
5
+ ---
6
+
7
+ # 0.2 算力与窗口的物理极限
8
+
9
+ 在 0.1 节中我们了解到,大模型是通过不断“接龙”来产生连续回答的。这自然引出了一个直观的问题:**为什么我们不能直接把一整本书、甚至整个数据库的历史记录一次性喂给大模型?为什么大模型一定要设置上下文窗口(Context Window)的上限?**
10
+
11
+ 许多人以为这仅仅是厂商为了多收费而设置的软件限制,但实际上,这是一个受制于现代半导体物理、数学算法以及 GPU 显存容量的**硬核物理极限**。
12
+
13
+ ---
14
+
15
+ ## 一、 Attention 机制的平方复杂度 $O(N^2)$
16
+
17
+ 现代大语言模型(如 GPT、Llama、Mistral)无一例外都是基于 **Transformer** 架构构建的。而 Transformer 的核心引擎,就是 **Self-Attention(自注意力机制)**。
18
+
19
+ ### 1. 什么是自注意力机制?
20
+ 自注意力机制的本质是:**计算输入序列中任意两个 Token 之间的语义相关性(权重)**。
21
+
22
+ 当大模型在预测下一个 Token 时,它需要回看前面所有的历史 Token。大模型通过将每个 Token 转化为三种角色向量来进行“匹配”:
23
+ * **Query (Q, 查询)**:我想找什么?
24
+ * **Key (K, 键)**:我这里有什么,可以被别人匹配?
25
+ * **Value (V, 值)**:我所代表的实际语义内容是什么?
26
+
27
+ 对于长度为 $N$ 的输入文本,模型需要计算 $Q$ 与 $K$ 之间的相关性权重矩阵。这意味着**每一个 Token 都要和前面所有的 Token 做一次点积(Dot Product)计算**。
28
+
29
+ ```
30
+ 输入序列长度 N = 4: ["今", "天", "天", "气"]
31
+
32
+ 相关性计算矩阵 (N x N):
33
+ 今 天 天 气
34
+ 今 [•] [•] [•] [•] ──> "今" 与所有字关联
35
+ 天 [•] [•] [•] [•] ──> "天" 与所有字关联
36
+ 天 [•] [•] [•] [•]
37
+ 气 [•] [•] [•] [•] ──> 共需要计算 4 x 4 = 16 次相关权重
38
+ ```
39
+
40
+ ### 2. $O(N^2)$ 的物理诅咒
41
+ 如果上下文长度为 $N$:
42
+ * 当 $N = 1,000$ 时,注意力权重矩阵的大小是 $1,000 \times 1,000 = 1,000,000$(100万次关联计算)。
43
+ * 当 $N = 10,000$ 时,计算量暴增至 $10,000 \times 10,000 = 100,000,000$(1亿次关联计算!)。
44
+ * 当 $N = 100,000$ 时,计算量将达到恐怖的 **100亿次**。
45
+
46
+ 这种随着上下文长度 $N$ 的增加,计算复杂度和所需的**临时激活显存(Activation Memory)**呈**平方级暴增**的现象,在算法上被称为 **$O(N^2)$ 复杂度**。
47
+
48
+ 这也是为什么当智能体的多轮对话历史变得极长时,大模型的推理速度(首字延迟 TTFT,Time-to-First-Token)会发生肉眼可见的急剧下滑,且服务器的计算开销呈指数飙升的底层原因。
49
+
50
+ ---
51
+
52
+ ## 二、 Context Window 与 KV Cache 的显存深渊
53
+
54
+ 为了解决每次“接龙”新 Token 时重复计算历史 Token 的 $Q, K, V$ 矩阵所带来的巨大算力浪费,工程上引入了一个核心优化技术:**KV Cache(键值缓存)**。但这个技术也带来了新的物理瓶颈。
55
+
56
+ ### 1. 什么是 KV Cache?
57
+ 当大模型生成第 $t$ 个 Token 时,前 $t-1$ 个 Token 的 Key(K)和 Value(V)向量其实已经在前面的步骤中计算过了,并且不会随着新 Token 的加入而改变。
58
+
59
+ 因此,推理引擎会把前 $t-1$ 个 Token 的 $K$ 和 $V$ 矩阵保存在 GPU 的显存中(这个缓存区就叫 KV Cache)。当生成第 $t$ 个 Token 时,模型只需要计算这一个新 Token 的 $Q, K, V$,然后直接去和显存里存好的历史 $K, V$ 做注意力点积。
60
+
61
+ ```
62
+ [步骤 t-1] 生成了 "好":
63
+ 将 "今", "天", "天", "气", "真", "好" 的 K, V 矩阵存入显存 (KV Cache)
64
+
65
+
66
+ [步骤 t] 准备生成下一个字:
67
+ 仅计算新字 "。" 的 Q, K, V ───> 与显存中的历史 K, V 进行 Attention 计算 ───> 吐出下一个字
68
+ ```
69
+
70
+ ### 2. KV Cache 显存占用公式
71
+ KV Cache 极大地节省了算力,但它是一个贪婪的**显存吞噬者**。我们可以用公式来精确计算 KV Cache 占用的显存字节数:
72
+
73
+ $$\text{Memory}_{\text{KV\_Cache}} = 2 \times B \times L \times H \times D \times N \times \text{Precision}$$
74
+
75
+ 其中:
76
+ * $2$ 代表 Key 和 Value 两个矩阵。
77
+ * $B$ 代表并发会话的 Batch Size(批大小)。
78
+ * $L$ 代表模型的层数(Layers,如 Llama 3-8B 有 32 层)。
79
+ * $H$ 代表注意力头的个数(Heads)。
80
+ * $D$ 代表每个头的维度(Dimension)。
81
+ * $N$ 代表当前的上下文 Token 数量。
82
+ * $\text{Precision}$ 代表参数精度占用的字节数(如 FP16 占用 2 字节,BF16 占用 2 字节)。
83
+
84
+ 以一个经典的 **Llama-3-8B** 模型在单用户($B=1$)、精度为 FP16(2字节)下运行,上下文长度 $N = 8,000$ 为例:
85
+ * 层数 $L = 32$
86
+ * K, V 注意力头数 $H = 8$(使用了 GQA 机制)
87
+ * 维度 $D = 128$
88
+ * 计算:$2 \times 1 \times 32 \times 8 \times 128 \times 8,000 \times 2 \approx 1,048,576,000 \text{ 字节} \approx \mathbf{1 \text{ GB}}$
89
+
90
+ 这意味着,**仅仅为了缓存这 8,000 个 Token 的记忆,在推理时就需要额外在 GPU 显存中霸占 1 GB 的空间**。这还没算模型本身参数占用的 16 GB 固化显存。如果高并发下有 64 个用户同时在线,光是 KV Cache 就会吃掉 64 GB 的显存,瞬间把一张顶级卡(如 A100 80GB)挤爆。
91
+
92
+ ---
93
+
94
+ ## 三、 长上下文的“大海捞针”瓶颈
95
+
96
+ 即便近年来通过 **FlashAttention** 算法优化了显存读写,以及通过 **RoPE 旋转位置编码**外推技术让模型号称支持 128k、1M 甚至 2M 的上下文窗口,但在物理上,长上下文的检索能力依然存在严重的瓶颈。
97
+
98
+ ### 1. 什么是“大海捞针”测试?
99
+ **“大海捞针”(Needle in a Haystack)**是测试长文本模型检索能力的标准实验。其方法是:在一篇长达数十万字的无聊小说(Haystack,干草堆)的随机位置,塞入一句完全不相干的秘密陈述(Needle,针,例如“小明最喜欢吃苹果”),然后将整个文本输入给大模型,要求它找出这句话。
100
+
101
+ ### 2. Lost in the Middle(迷失在中间)现象
102
+ 经过大量学术界和工业界的评测,人们发现了一个残酷的物理事实:
103
+ 当上下文长度达到极限时,模型对于首部(Prompt 开头)和尾部(Prompt 结尾)的信息检索准确率接近 100%。但是,**对于处于上下文中段(Middle)的信息,检索准确率会发生断崖式下跌,甚至直接漏掉**。
104
+
105
+ ```
106
+ 信息检索准确率曲线 (U型曲线):
107
+
108
+ 准确率 100% | \ /
109
+ | \ /
110
+ | \ /
111
+ | \ /
112
+ | \ Lost /
113
+ | \ in the Middle /
114
+ 0% | \____________[降温区]_________/
115
+ +---------------------------------------------------
116
+ 0% (文档开头) 50% (文档中段) 100% (文档结尾)
117
+ ```
118
+
119
+ 这是因为 Transformer 的 Attention 权重在面对庞大序列时,长距离的信号会受到稀释和干扰,导致模型“注意力涣散”。因此,**支持 1M 的上下文窗口,并不等于模型能够真正消化 1M 的全部信息**。
120
+
121
+ ---
122
+
123
+ ## 四、 【架构防范】上下文膨胀与 Token 费用失控控制
124
+
125
+ 在 Agent 系统开发中,由于 Agent 会频繁调用外部工具并带回大量的 Observation 结果,会导致上下文(Context)极速膨胀。如果不做策略防御,会导致 API 计费风暴(Token 刺客)与请求报错。
126
+
127
+ ### 1. API 计费风暴与窗口超限
128
+
129
+ 当我们调用云端大模型 API(如 OpenAI、Gemini 或国产的 DeepSeek、Qwen 等)时,每次发送新的对话请求,推理引擎都需要对所有的历史文本、多模态附件以及工具返回结果进行重新读取和处理。这意味着:
130
+ * **输入计费线性滚雪球**:随着会话轮数的增加,每一轮你都需要为“历史对话和所有工具返回”重复买单。Input Token 计费会像滚雪球一样线性暴增,即使大模型单次只吐出几个字的回复,前台的账单也会非常昂贵。
131
+ * **超出窗口极限报错(400 Bad Request)**:当总 Token 数超过大模型 API 所允许的最大输入限制时,请求会直接被大模型关口拦截并报错挂死。
132
+ * **静默截断导致智能体“脑残”**:部分厂商的 API 在超限时不会报错,而是采取“后进先出”的机制静默截断头部历史(这往往会把最顶部的系统设定 `System Prompt` 强行丢弃),导致 Agent 瞬间丧失身份设定或工具规范。
133
+
134
+ ### 2. Agent 成本与窗口控制策略
135
+
136
+ 为了让 Agent 在预算和物理窗口的双重极限内健康运转,我们在 Freya 架构设计中必须采取以下防御机制:
137
+
138
+ 1. **主动上下文监控与滚动摘要(Compactor)**:
139
+ 在底座发起大模型 API 调用前,实时计算当前会话的消息总 Token 数。一旦逼近安全限额或预设的预算上限,主动触发 Compactor 机制对历史长文本进行精炼摘要,释放大量上下文配额,从而降低每轮的 Input Token 账单。
140
+ 2. **闲置工具动态淘汰机制**:
141
+ 在 Agent 开发中,工具箱的定义(JSON Schema)会作为 System Prompt 的一部分在每轮中被重算。如果挂载了几十个工具,即便不调用,也会持续消耗大量的 Input Token 费用。应当实时监测工具调用频率,自动动态卸载(Deactivate)连续多轮未被调用的工具箱,大幅精简 Prompt 体积。
142
+ 3. **计费监控与死循环费用熔断(Billing & Abort Safeguards)**:
143
+ 在 Agent 大脑主循环(ReAct 循环)中,必须配置全局计费监控。一旦检测到单次会话或单轮交互的 Token 累积费用超出安全阈值(例如触发了无限工具调用死循环),底座必须立即强行向 LLM 发送 `AbortSignal` 进行“紧急刹车”,物理熔断扣费。
144
+
145
+ 通过本节的物理剖析,我们必须清醒地认识到:**API 窗口是有极限的,Token 是极其昂贵的**。在后续的架构开发中,我们将看到 Freya 如何在 `SessionManager` 中通过精密的物理限额、闲置工具动态淘汰和 Compactor 机制,在满足业务需求的同时,牢牢守住开发者的资金安全底线。
@@ -0,0 +1,132 @@
1
+ ---
2
+ title: "0.3 随机与严谨的博弈"
3
+ weight: 30
4
+ description: "深入 Softmax 概率转化与温度控制公式,解析 Temperature、Top-P、Top-K 采样的数学本质与 Agent 调优策略。"
5
+ ---
6
+
7
+ # 0.3 随机与严谨的博弈
8
+
9
+ 在前面的学习中,我们反复提到大模型在进行“文字接龙”时预测的是下一个 Token 的**概率分布**。然而,光有概率分布还不够,我们还需要决定**如何从这个分布中挑选出最终的那一个 Token**。
10
+
11
+ 在调用各种 LLM API 时,我们会遇到诸如 `temperature`(温度)、`top_p`(核采样)、`top_k`、`frequency_penalty` 等生成参数。这些参数绝对不是什么虚无飘渺的“创造力滑块”,它们在底层都是非常纯粹且严谨的**概率数学公式**。
12
+
13
+ 作为智能体(Agent)的架构师,理解并微调这些参数,是控制 Agent 决策严谨度、防止其产生幻觉(Hallucination)的第一道物理防线。
14
+
15
+ ---
16
+
17
+ ## 一、 从 Logits 到概率分布:Softmax 的魔法
18
+
19
+ 当大模型的最后一层(Linear Layer)计算完毕后,它向外输出的是一个巨大的浮点数数组,数组的长度等于词表(Vocabulary)的大小(通常为几万到十万)。这个数组里的每一个数值被称为 **Logits(未归一化的原始得分)**。
20
+
21
+ Logits 并不是概率,它们的数值范围是任意的实数(比如 `12.5`、`-3.2`、`0.1`)。为了将它们转化为和为 1 的、大模型能够理解的“概率”,大模型会使用数学上的 **Softmax 函数**:
22
+
23
+ $$P(x_i) = \frac{e^{z_i}}{\sum_{j} e^{z_j}}$$
24
+
25
+ 其中:
26
+ * $z_i$ 代表第 $i$ 个 Token 的 Logits 原始得分。
27
+ * $P(x_i)$ 代表归一化后,该 Token 被选中的概率。
28
+
29
+ ```
30
+ 原始得分 Logits ───> [ 5.2, 2.65, -1.65, 1.15 ]
31
+
32
+ ▼ (通过 Softmax 计算)
33
+ 归一化概率 P(x) ───> [ 91.2%, 7.1%, 0.1%, 1.6% ] (总和为 100%)
34
+ ```
35
+
36
+ 这一步骤将原始的混乱得分,成功翻译成了符合概率论的候选词列表。
37
+
38
+ ---
39
+
40
+ ## 二、 Temperature(温度)的数学物理本质
41
+
42
+ **Temperature(温度)** 参数的作用,就是在执行 Softmax 转化之前,人工干预 Logits 原始得分的数值分布。
43
+
44
+ ### 1. 带温度参数的 Softmax 公式
45
+ 带温度参数的 Softmax 公式如下:
46
+
47
+ $$P(x_i) = \frac{e^{z_i / T}}{\sum_{j} e^{z_j / T}}$$
48
+
49
+ 公式中,我们引入了一个除数 $T$(即 Temperature)。正是这个除数 $T$ 的大小变化,改变了归一化后概率曲线的平缓度。
50
+
51
+ ### 2. 当 $T \to 0$ 时(低温区):严谨与确定性
52
+ 当我们将温度 $T$ 设置为接近 $0$(例如 $T=0.1$ 甚至 $T=0.0$)时,公式中的分母分之分子会产生剧烈的拉伸效应:
53
+ * 原本得分最高的那个 Token,在除以一个极小的数之后,其指数值 $e^{z_i / T}$ 会呈几何级数膨胀,远远甩开其他候选词。
54
+ * 进行 Softmax 归一化后,**排名第一的候选词概率会趋近于 100%,而其余候选词的概率则会被无限压低至 0%**。
55
+
56
+ 在工程上,当 $T=0$ 时,模型实际上是在做**贪婪解码(Greedy Decoding)** —— 永远只挑选概率最大的那个词。这种状态下,Agent 最为理性和严谨,每次给出相同的输入,它都会返回完全一致、高度确定的输出。这在提取 JSON 数据、编写代码或执行精确检索时是必须的。
57
+
58
+ ### 3. 当 $T \ge 1.0$ 时(高温区):随机与创造力
59
+ 当我们将温度 $T$ 调高(例如 $T=1.5$ 甚至更大)时:
60
+ * Logits 中每个词的得分除以一个大于 1 的数,它们之间的数值差距会被大幅“压缩”、拉近。
61
+ * 进行 Softmax 归一化后,概率分布曲线会变得非常平缓(Flat)。
62
+ * 原本概率很低的生僻 Token,其被选中的概率会显著上升。
63
+
64
+ 这会使 Agent 的行为变得极其活泼、富有“想象力”(创造性写作)。但物理代价非常明显:由于随机挑选了低概率的词,大模型的接龙逻辑链会发生碎裂,开始胡言乱语,产生严重逻辑错误和胡说八道的“幻觉”。
65
+
66
+ ```
67
+ 不同温度下的概率分布示意图:
68
+
69
+ P(x) ↑ [ 99% ] P(x) ↑
70
+ | | |
71
+ | | | [ 35% ] [ 28% ]
72
+ | | | | | [ 20% ]
73
+ | |____[ 1% ] | | | | __[ 17% ]
74
+ +-------------------> 候选词 +----------------------------------> 候选词
75
+ T = 0.1 (陡峭/确定) T = 1.5 (平缓/随机)
76
+ ```
77
+
78
+ ---
79
+
80
+ ## 三、 候选池的修建:Top-P 与 Top-K 采样
81
+
82
+ 为了在享受“高温”带来的创造性的同时,防止模型选择到那些概率极低、近乎荒谬的 Token,我们需要在采样前对候选池进行“修建”。
83
+
84
+ ### 1. Top-K 采样(按数量截断)
85
+ **Top-K** 参数规定:**在进行 Softmax 概率挑选之前,只保留 Logits 得分最高的前 $K$ 个 Token,将其余的所有词强行剔除出候选池。**
86
+
87
+ 例如,设置 $K=50$:模型无论多么想要“放飞自我”,也只能在概率最高的前 50 个候选词里挑选。这能够有效防止模型在高温区选到逻辑完全不通的垃圾字符。
88
+
89
+ ### 2. Top-P 采样(核采样,Nucleus Sampling)
90
+ 虽然 Top-K 很管用,但它有一个硬伤:**截断数量是固定的**。
91
+ * 在某些语义高度确定的上下文下(如“我最爱吃苹果和香_”),前两名候选词的概率已经达到了 99%。此时如果依然在前 $K=50$ 个词里挑选,就会把剩下 1% 极小概率的垃圾词卷入采样。
92
+ * 在某些语义非常宽泛的上下文下,前 50 个词的概率加起来可能还不到 30%。此时强行把后面的候选词截断,又会严重削弱创造力。
93
+
94
+ 为了解决这一问题,学术界提出了 **Top-P(核采样)**。它的逻辑是:**将所有候选 Token 按照概率从大到小排序,从前往后累加它们的概率,当累加和达到设定的阈值 $P$ 时停止,只保留这部分累加进来的 Token 组合作为候选池。**
95
+
96
+ ```
97
+ 候选词排序: {"苹果": 50%, "香蕉": 30%, "橘子": 12%, "石头": 5%, "飞机": 3%}
98
+ 若设置 Top-P = 0.9 (累加到 90% 截断):
99
+ 1. 累加 "苹果" (50%) < 90%
100
+ 2. 累加 "香蕉" (50%+30%=80%) < 90%
101
+ 3. 累加 "橘子" (80%+12%=92%) >= 90% ──> 停止!
102
+ 候选池保留: ["苹果", "香蕉", "橘子"],其余 "石头"、"飞机" 被无情过滤。
103
+ ```
104
+
105
+ Top-P 能够自适应地根据上下文的确定性来动态收缩或扩张候选池,在 Agent 交互设计中更为常用。
106
+
107
+ ---
108
+
109
+ ## 四、 频率惩罚与存在惩罚 (Frequency / Presence Penalty)
110
+
111
+ 有时候,大模型在生成较长文本时,会像“复读机”一样反复念叨同一个词或者短语。为了打破这种循环,大模型 API 引入了两个微调 Logits 的惩罚参数:
112
+
113
+ 1. **Presence Penalty(存在惩罚)**:
114
+ 只要某个 Token 在已经生成的文本里出现过(不管出现了多少次),就在其下一步预测的 Logits 得分上强行减去一个常数惩罚项。这会极大地促使大模型引入全新的话题和词汇。
115
+ 2. **Frequency Penalty(频率惩罚)**:
116
+ 根据某个 Token 在已生成文本中出现的**频次**进行累加惩罚(出现次数越多,罚得越重)。这能有效防止大模型在输出长文时反复使用某些口头禅(如“显而易见”、“总而言之”)。
117
+
118
+ ---
119
+
120
+ ## 五、 【架构调优】智能体不同任务场景下的参数推荐
121
+
122
+ 在设计 Freya 这样的 Agent 系统底座时,我们需要针对智能体执行的不同子任务,动态下发不同的参数组合。千万不要全用一套默认参数:
123
+
124
+ | 任务场景 | 推荐参数配置 | 科学道理 |
125
+ | :--- | :--- | :--- |
126
+ | **Tool Call 参数提取 / 结构化 JSON 输出** | $T=0.0$, $\text{Top-P}=1.0$ | 此时需要极致的逻辑确定性,Tool 调用参数一旦随机错一个字符(如 `userId` 拼成 `userid`),后端接口就会报错崩溃。 |
127
+ | **代码生成与语法纠错 (Coding)** | $T=0.1 \sim 0.2$, $\text{Top-P}=0.9$ | 代码需要高度严谨,但在算法编写上允许存在微弱的结构自适应。 |
128
+ | **多轮对话 / 任务规划决策 (Planning)** | $T=0.3 \sim 0.5$, $\text{Top-P}=0.85$ | 在保持严谨主逻辑线的同时,给智能体保留一定的思路自适应弹性,防止陷入思路死角。 |
129
+ | **创意写作 / 角色扮演 (Creative)** | $T=0.8 \sim 0.9$, $\text{Top-P}=0.9$ | 允许发挥联想,但限制在 90% 的合理概率池内,防止彻底胡言乱语。 |
130
+
131
+ ### ⚠️ 架构避坑警示:不要同时把 Temperature 和 Top-P 调高
132
+ 如果你的 Agent 底座同时将 Temperature 设为 `1.8`,将 Top-P 设为 `1.0`(不限制候选池),采样概率会发生彻底的碎裂化。大模型会生成大量乱码、甚至是无法识别的二进制字符,导致智能体的 JSON 解析器彻底瘫痪。在编写系统配置层时,必须对这类参数交界进行逻辑上的安全限额限制。