Prompt 与流式响应
System Prompt
System Prompt 定义了 Agent 的行为规则和能力边界。
基本结构
typescript
const systemPrompt = `你是一个编程助手。
## 能力
- 你可以读写文件
- 你可以执行 shell 命令
- 你可以搜索代码
## 规则
- 执行危险操作前要确认
- 每次只做一件事
- 遇到错误时说明原因
`gemini-cli 的 System Prompt
gemini-cli 的 System Prompt 在 packages/core/src/core/prompts.ts,包含:
- Agent 身份定义
- 工具使用说明
- 代码规范要求
- 安全限制
- 输出格式
关键点:
- 明确告诉 LLM 它有哪些工具
- 说明每个工具的使用场景
- 定义行为边界和限制
上下文构建
Agent 每次调用 LLM 时,需要传入完整的对话上下文:
typescript
const messages = [
{ role: 'user', content: '读取 config.json' },
{ role: 'model', content: '', functionCall: { name: 'read_file', args: { path: 'config.json' } } },
{ role: 'function', name: 'read_file', content: '{"name": "my-app"}' },
{ role: 'model', content: 'config.json 的内容是...' },
{ role: 'user', content: '把 name 改成 new-app' },
// ... LLM 需要看到完整历史才能理解上下文
]流式响应
为什么需要流式
- 用户体验更好:不用等待完整响应
- 长回复不会超时
- 可以实时显示思考过程
基本用法
typescript
const result = await chat.sendMessageStream('解释量子计算')
for await (const chunk of result.stream) {
const text = chunk.text()
process.stdout.write(text) // 实时输出
}处理流式中的工具调用
流式响应中也可能包含工具调用:
typescript
const result = await chat.sendMessageStream(userMessage)
let functionCalls = []
let textContent = ''
for await (const chunk of result.stream) {
// 累积文本
textContent += chunk.text() || ''
// 检查工具调用
const calls = chunk.functionCalls()
if (calls) {
functionCalls.push(...calls)
}
}
// 流结束后处理
if (functionCalls.length > 0) {
// 执行工具...
} else {
console.log(textContent)
}gemini-cli 中的实现
gemini-cli 使用事件系统处理流式响应。
源码位置:packages/core/src/core/geminiChat.ts
简化的流式处理逻辑:
typescript
async *streamResponse(contents: Content[]) {
const result = await this.chat.sendMessageStream(contents)
for await (const chunk of result.stream) {
// 发射文本事件
const text = chunk.text()
if (text) {
yield { type: 'text', content: text }
}
// 发射工具调用事件
const functionCalls = chunk.functionCalls()
if (functionCalls) {
yield { type: 'functionCall', calls: functionCalls }
}
}
}gemini-cli 定义了多种事件类型(在 turn.ts 中):
Content- 文本内容ToolCallRequest- 工具调用请求ToolCallResponse- 工具执行结果Thought- 思考过程Error- 错误
Prompt 优化技巧
1. 明确的工具说明
typescript
{
name: 'edit_file',
description: `编辑文件内容。
使用场景:修改现有文件的部分内容
注意:只替换指定的部分,不要重写整个文件
参数说明:
- path: 文件路径
- old_text: 要替换的原文本(必须精确匹配)
- new_text: 新文本`
}2. 少即是多
不要给 LLM 太多工具,会增加选择困难。gemini-cli 的内置工具也就十几个。
3. 提供示例
typescript
const systemPrompt = `
## 示例
用户: 帮我创建一个 React 组件
你应该:
1. 先问用户组件名称和功能
2. 创建组件文件
3. 如果需要,创建对应的测试文件
`完整示例
typescript
import { GoogleGenerativeAI } from '@google/generative-ai'
async function streamingAgent() {
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY!)
const model = genAI.getGenerativeModel({
model: 'gemini-2.5-flash',
systemInstruction: '你是一个友好的编程助手。回答要简洁。'
})
const chat = model.startChat()
// 流式发送
const result = await chat.sendMessageStream('用 3 句话解释什么是 API')
console.log('回复: ')
for await (const chunk of result.stream) {
process.stdout.write(chunk.text() || '')
}
console.log('\n完成')
}
streamingAgent()小结
- System Prompt 定义 Agent 的行为和能力
- 每次调用需要传入完整对话历史
- 流式响应提升用户体验
- 工具描述要清晰、具体
下一步
了解了 API 基础,接下来深入学习工具系统:Function Calling 原理 →