3.1 上下文的重要性

概述

在多轮对话中,上下文(Context)是让 AI 能够理解对话历史的关键。没有上下文,AI 无法记住之前说过的话,每次对话都是独立的。

什么是上下文

定义

上下文是对话历史中的所有消息,包括:

  • 系统提示(System)
  • 用户消息(User)
  • AI 回复(Assistant)
  • 工具调用和结果(Tool)

为什么需要上下文

场景 1:指代消解

1
2
3
4
用户:什么是 TypeScript?
AI:TypeScript 是 JavaScript 的超集...
用户:它有什么优点?
AI:[没有上下文,无法理解"它"指的是什么]

场景 2:信息延续

1
2
3
4
用户:帮我创建一个待办事项应用
AI:好的,使用什么框架?
用户:使用 React
AI:[需要记住"创建待办事项应用"这个目标]

场景 3:任务跟踪

1
2
3
4
用户:读取 data.json
AI:[读取文件内容]
用户:分析其中的销售数据
AI:[需要知道上一步读取了什么内容]

上下文窗口

什么是 Token

LLM 处理文本的基本单位。粗略估计:

  • 1 Token ≈ 0.75 个英文单词
  • 1 Token ≈ 2-3 个汉字

上下文限制

不同模型有不同的上下文窗口:

模型 上下文窗口
GPT-3.5 4K / 16K tokens
GPT-4 8K / 32K tokens
Claude 100K+ tokens
DeepSeek 32K tokens

Token 计算示例

1
2
3
4
5
6
7
8
// 简单的 token 计算方法
function estimateTokens(text: string): number {
// 粗略估计:英文 4 字符 = 1 token,中文 1.5 字符 = 1 token
const englishChars = text.match(/[a-zA-Z]/g)?.length || 0;
const chineseChars = text.match(/[\u4e00-\u9fa5]/g)?.length || 0;

return Math.ceil(englishChars / 4 + chineseChars / 1.5);
}

消息历史结构

基本结构

1
2
3
4
5
6
interface Message {
role: 'system' | 'user' | 'assistant' | 'tool';
content: string;
}

type ConversationHistory = Message[];

完整示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const history: Message[] = [
// 系统提示
{
role: 'system',
content: '你是一个编程助手,擅长 TypeScript。'
},

// 第一轮对话
{
role: 'user',
content: 'TypeScript 是什么?'
},
{
role: 'assistant',
content: 'TypeScript 是 JavaScript 的超集,添加了静态类型...'
},

// 第二轮对话(依赖第一轮的上下文)
{
role: 'user',
content: '它和 JavaScript 有什么区别?' // "它" 指 TypeScript
},
{
role: 'assistant',
content: '主要区别在于 TypeScript 添加了类型系统...'
}
];

上下文管理策略

1. 全量保存(简单但有限制)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let history: Message[] = [];

async function chat(userMessage: string) {
history.push({ role: 'user', content: userMessage });

const response = await openai.chat.completions.create({
model: 'deepseek-chat',
messages: history
});

const assistantMessage = response.choices[0].message.content;
history.push({ role: 'assistant', content: assistantMessage });

return assistantMessage;
}

优点: 简单直接
缺点: 会超过上下文窗口限制

2. 滑动窗口(推荐)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const MAX_TOKENS = 4000;
let history: Message[] = [];

async function chat(userMessage: string) {
history.push({ role: 'user', content: userMessage });

// 计算当前 token 数量
let tokenCount = estimateTokens(JSON.stringify(history));

// 如果超过限制,删除最旧的消息(保留系统消息)
while (tokenCount > MAX_TOKENS && history.length > 2) {
history.splice(1, 1); // 删除第一条非系统消息
tokenCount = estimateTokens(JSON.stringify(history));
}

const response = await openai.chat.completions.create({
model: 'deepseek-chat',
messages: history
});

const assistantMessage = response.choices[0].message.content;
history.push({ role: 'assistant', content: assistantMessage });

return assistantMessage;
}

3. 智能摘要(高级)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
interface Summary {
summary: string;
lastMessages: Message[];
}

let conversationState: Summary = {
summary: '',
lastMessages: []
};

async function chat(userMessage: string) {
conversationState.lastMessages.push({
role: 'user',
content: userMessage
});

// 如果消息太多,生成摘要
if (conversationState.lastMessages.length > 10) {
conversationState.summary = await generateSummary(
conversationState.summary,
conversationState.lastMessages
);
conversationState.lastMessages = [];
}

// 构建完整消息
const messages: Message[] = [
{ role: 'system', content: conversationState.summary },
...conversationState.lastMessages
];

const response = await openai.chat.completions.create({
model: 'deepseek-chat',
messages
});

return response.choices[0].message.content;
}

最佳实践

1. 保留系统消息

1
2
3
4
5
6
7
8
// 好的做法
const history: Message[] = [
{ role: 'system', content: systemPrompt }, // 始终保留
...conversationMessages
];

// 不好的做法
const history: Message[] = conversationMessages; // 丢失系统提示

2. 控制历史长度

1
2
3
4
5
const MAX_HISTORY = 20;  // 最多保留 20 条消息
if (history.length > MAX_HISTORY) {
history = history.slice(-MAX_HISTORY);
history.unshift(systemMessage); // 重新添加系统消息
}

3. 处理工具调用

1
2
3
4
5
6
7
8
9
10
11
12
13
interface ToolMessage extends Message {
role: 'tool';
tool_call_id: string;
content: string;
}

// 工具调用也会占用上下文
const history: Message[] = [
{ role: 'user', content: '读取文件' },
{ role: 'assistant', content: '', tool_calls: [...] },
{ role: 'tool', content: '文件内容...', tool_call_id: '...' },
{ role: 'assistant', content: '这是文件内容...' }
];

总结

上下文管理是 AI Agent 的基础:

  • 理解对话历史 - AI 能够理解之前的内容
  • 指代消解 - 理解”它”、”这个”等代词
  • 任务延续 - 跟踪长期任务
  • 窗口管理 - 处理 token 限制

下一节将实现具体的消息历史存储。

导航

上一篇: 2.3 代码结构分析

下一篇: 3.2 消息历史存储