Agent 02:加上多轮对话
上一章最后发现,现在只能聊一次。模型回答完,程序就结束了。
那多轮对话怎么搞?
我的理解其实很简单,就是搞一个数组,然后把我的输入和模型的回答都保存起来。
typescript
const messages: ChatCompletionMessageParam[] = [];我输入一句,就往里面塞一条:
typescript
messages.push({ role: 'user', content: prompt });模型回答以后,也往里面塞一条:
typescript
messages.push({ role: 'assistant', content });整个顺序就是这样:
text
第一次输入
↓ push
messages: [user1]
↓ 发送给模型
第一次输出
↓ push
messages: [user1, assistant1]
↓ 下一次输入,再 push
messages: [user1, assistant1, user2]
↓ 发送给模型
第二次输出
↓ push
messages: [user1, assistant1, user2, assistant2]比如我先告诉它“我叫小明”,然后再问它“我叫什么”,这个数组差不多就是这样:
typescript
[
{ role: 'user', content: '我叫小明' },
{ role: 'assistant', content: '你好,小明' },
{ role: 'user', content: '我叫什么?' },
]下一次请求的时候,再把整个数组发给模型:
typescript
const completion = await client.chat.completions.create({
model: 'deepseek-v4-flash',
messages,
});这样模型就能看到前面聊过什么了。
但是数组只解决了模型记不住的问题,程序还是会执行完就结束。
按照前面单轮对话的写法,程序从上往下执行。我输入一句,模型输出一句,代码走到最后,程序也就结束了。
那怎么能让程序不退出呢?
这里就要用到 while:
typescript
while (true) {
const prompt = (await readline.question('You: ')).trim();
// 请求模型并输出回答
}回答输出以后,这一轮就走完了。因为外面还有一个 while,代码会重新回到开头,再执行一次 question(),等我继续输入。
text
等待输入
→ 模型回答
→ 回到 while 开头
→ 再次等待输入while (true) 会一直循环,所以还要留一个退出方式:
typescript
if (prompt === '/exit') {
break;
}输入 /exit,通过 break 跳出这个循环,程序才会结束。
完整代码:
typescript
import { stdin, stdout } from 'node:process';
import { createInterface } from 'node:readline/promises';
import OpenAI from 'openai';
import type { ChatCompletionMessageParam } from 'openai/resources/chat/completions.js';
const apiKey = process.env.DEEPSEEK_API_KEY;
if (!apiKey) {
throw new Error('Missing DEEPSEEK_API_KEY');
}
const client = new OpenAI({
apiKey,
baseURL: 'https://api.deepseek.com',
});
const readline = createInterface({ input: stdin, output: stdout });
const messages: ChatCompletionMessageParam[] = [];
try {
while (true) {
const prompt = (await readline.question('You: ')).trim();
if (prompt === '/exit') {
break;
}
if (!prompt) {
continue;
}
messages.push({ role: 'user', content: prompt });
try {
const completion = await client.chat.completions.create({
model: 'deepseek-v4-flash',
messages,
});
const content = completion.choices[0]?.message.content;
if (!content) {
throw new Error('DeepSeek returned an empty response');
}
messages.push({ role: 'assistant', content });
console.log(`DeepSeek: ${content}`);
} catch (error) {
messages.pop();
console.error(error instanceof Error ? error.message : String(error));
}
}
} finally {
readline.close();
}核心其实就是这个 messages。把双方说过的话都保存起来,每次再一起发给模型,多轮对话就有了。
然后我启动起来试了一下,发现它现在确实有记忆了。前面说过的话,后面再问,它能接得上。
但是又有一点体验不好。我输入完以后,模型没有马上返回,这中间终端里什么反馈都没有,我也不知道它到底有没有在处理。
所以下一章准备给这个对话加一个 loading。