☰
LLM Context Management 学习笔记
2026/9/27 1:57:49 网站建设 项目流程

1. 本章目标

目标是解决多轮 LLM 对话中的核心问题:

Chat History 会不断增长,而模型的 Context Window 是有限的。

因此后端需要完成:

多轮聊天 ↓ Token 统计 ↓ 判断是否超限 ↓ 历史裁剪 ↓ 旧对话总结 ↓ Summary 压缩 ↓ 重新构造 Context ↓ 保证最终输入处于 Token Budget 内

2. Token / Token ID / Embedding

三者不能混淆。

Text ↓ Tokenizer ↓ Token ↓ Token ID ↓ Embedding Layer ↓ Vector ↓ Transformer

Token

Token 是 tokenizer 对文本进行切分后得到的离散单位。

它不是向量。

例如:

"I love AI" ↓ ["I", " love", " AI"]

Token ID

每个 token 会对应一个整数编号:

["I", " love", " AI"] ↓ [40, 3021, 15592]

Embedding

Token ID 再经过 Embedding Layer:

40 ↓ [0.12, -0.34, 0.88, ...]

这里才真正变成向量。


3. Context Window

Context Window 可以理解成:

模型单次调用能够处理的 Token 总预算。

通常需要考虑:

System Prompt + Conversation History + RAG Documents + Current User Query + Model Output

因此:

Input Tokens + Output Tokens <= Context Window

不能把全部 Context Window 都分给输入。

例如:

Context Window = 8000 Input Budget = 7000 Output Reserve = 1000

4. Token Estimate

学习阶段使用简单近似:

def estimate_tokens(text: str) -> int: return max(1, len(text) // 4)

注意:

这只是粗略估算。

真实项目应该使用具体模型对应的 tokenizer。


5. 统计整个 Context

def count_message_tokens( messages: list[dict] ) -> int: total_tokens = 0 for message in messages: total_tokens += estimate_tokens( message["content"] ) return total_tokens

逻辑:

message 1 → token message 2 → token message 3 → token ... ↓ total_tokens

6. Message-based Trimming

最简单的 Context Management:

始终保留 System Prompt + 只保留最近 N 条消息

例如:

def trim_messages( messages: list[dict], max_messages: int ) -> list[dict]: if not messages: return [] if max_messages <= 0: return [] system_message = messages[0] if max_messages == 1: return [system_message] recent_messages = messages[1:][-(max_messages - 1):] return [ system_message, *recent_messages ]

缺陷:

消息数量 ≠ Token 数量

一条消息可能只有:

OK

也可能是一篇 5000 字文章。

所以进一步进入 Token-based Trimming。


7. Token-based Trimming

目标:

System Prompt 永远保留 + 从最近的消息开始向前选择 + 直到达到 Token Budget

核心:

for message in reversed(messages[1:]):

因为最近的聊天通常比很早以前的聊天更加重要。

选完以后:

selected.reverse()

恢复正常时间顺序。


8. Conversation Summary

直接删除旧历史会造成信息永久丢失。

因此可以:

Old History ↓ LLM Summarization ↓ Conversation Summary

最终 Context:

System Prompt + Conversation Summary + Recent Messages

这样可以用更少 Token 保留更早的重要信息。


9. messages_to_text()

LLM 做总结之前,需要把:

list[dict]

转换成文本:

def messages_to_text( old_messages: list[dict] ) -> str: return "\n".join( f'{message["role"]}: {message["content"]}' for message in old_messages )

这里组合了:

Generator Expression + join()

例如:

[ {"role": "user", "content": "What is RAG?"}, {"role": "assistant", "content": "RAG combines retrieval and generation."} ]

变成:

user: What is RAG? assistant: RAG combines retrieval and generation.

10. summarize_messages()

旧聊天通过 LLM 转换成 Summary:

old_messages ↓ messages_to_text() ↓ summary prompt ↓ LLMClient.chat() ↓ result["answer"] ↓ summary

总结时应保留:

  • Important facts

  • User goals

  • Decisions

  • Constraints

  • Unresolved questions

Summary 的重点是:

信息保真,而不是创造性。

因此通常使用相对低的 temperature。


11. build_context()

将:

System + Summary + Recent Messages

重新组合:

def build_context( system_message: dict, summary: str, recent_messages: list[dict] ) -> list[dict]: summary_message = { "role": "system", "content": f"Conversation summary: {summary}" } return [ system_message, summary_message, *recent_messages ]

12. Context Priority

不是所有 Context 信息优先级都一样。

可以建立:

Priority 1 System Prompt Priority 2 Current User Query Priority 3 Conversation Summary Priority 4 Recent History Priority 5 Very Old History

未来加入 RAG:

System Prompt + Conversation Summary + Recent History + Retrieved Documents + Current Query

这就是:

Context Budget Allocation


13. Summary Compression

如果:

System + Summary

本身已经超过预算,那么删除 Recent History 也没有意义。

这时应该:

Summary ↓ 再压缩 ↓ 更短 Summary

但不能无限循环。

应该使用:

Bounded Retry

例如:

MAX_SUMMARY_RETRIES = 2

最多尝试 2 次。

如果仍然超限:

raise ContextOverflowError(...)

14. 为什么不能无限总结

无限循环可能产生:

  • 无限 API 调用

  • 无限费用

  • 延迟不断增加

  • Summary 信息持续丢失

  • Summary 不一定越来越短

  • 程序可能无法终止

因此真实工程要求:

压缩 ↓ 有限次数 ↓ 重新检查 ↓ 仍然失败 ↓ Fallback / Error

15. Responsibility Separation

这一章很重要的软件设计思想:

trim_context()

只负责:

在固定 Context 合法的情况下 尽量保留 Recent History

summarize_messages()

只负责:

Messages → Summary

compress_summary()

只负责:

Long Summary → Short Summary

prepare_context()

负责整个流程:

检查 ↓ 拆分 ↓ 总结 ↓ 压缩 ↓ 裁剪 ↓ 异常处理

也就是:

prepare_context() 是 Orchestrator / Controller。


16. 本章最终架构

messages │ ▼ prepare_context() │ Token Count │ ┌──────────┴──────────┐ │ │ 未超预算 超预算 │ │ return messages ▼ Split History │ ┌─────────────┴─────────────┐ ▼ ▼ old_messages recent_messages │ │ ▼ │ summarize_messages() │ │ │ ▼ │ summary │ │ │ ▼ │ fixed context │ system + summary │ │ │ ▼ │ 是否超预算? │ / \ │ No Yes │ │ │ │ │ compress_summary() │ │ │ │ │ 最多 N 次 │ │ │ │ │ 仍然超预算? │ │ / \ │ │ No Yes │ │ │ │ │ │ │ Error │ │ │ │ └───────┴───────────────┐ ▼ trim_context() │ ▼ Final Context

17. 本章涉及的 Python 知识

本章实际上复习并组合了:

list dict slice reversed() reverse() for loop generator expression join() f-string function typing class exception async / await OOP LLMClient nested dict early return

最大的提升不是又学了几个 Python 语法,而是开始:

把多个函数组合成一个完整 AI Backend 子系统。


18. 当前学习进度

Python Fundamentals ✅ FastAPI / Pydantic ✅ Async HTTP / LLMClient ✅ LLM Messages ✅ Multi-turn Chat ✅ Context Management ✅ 本章完成 Structured Output ← 下一章 Tool Calling ⏳ Embedding ⏳ Vector Database ⏳ RAG ⏳ Agent ⏳ Production / Deployment ⏳

下一阶段:

Structured Output → Tool Calling → RAG → Agent

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询