基于Microsoft vscode-copilot-chat开源项目的深度分析,总结现代AI助手中提示词构建和响应格式控制的完整解决方案。
📋 目录
1. 概述
在构建现代AI助手时,我们面临两个核心挑战:
- 如何构建结构化、易理解的提示词?
- 如何获取可靠的格式化输出?
通过对vscode-copilot-chat项目的深入分析,我们发现了一套成熟的解决方案:
用途 |
方法 |
可靠性 |
适用场景 |
构建提示词 |
Tag标签 |
⭐⭐⭐⭐⭐ |
组织复杂提示词结构 |
格式化输出 |
Function Call |
⭐⭐⭐⭐⭐ |
获取可靠的结构化数据 |
2. 提示词构建:Tag标签方法
2.1 核心原理
现代大语言模型对结构化标签有天然的理解优势,XML/HTML标签比纯文本更容易被准确解析。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// vscode-copilot-chat的Tag组件实现
export class Tag extends PromptElement<TagProps> {
render() {
const { name, children, attrs = {} } = this.props;
return (
<>
<KeepWith>{`<${name}${attrStr}>\n`}</KeepWith>
<TagInner priority={1} flexGrow={1}>{children}<br /></TagInner>
<KeepWith>{`</${name}>`}</KeepWith>
</>
);
}
}
|
2.2 标签分类系统
🎯 指令类标签
1
2
3
4
5
6
7
|
<instructions>
You are a highly sophisticated automated coding agent with expert-level knowledge...
</instructions>
<toolUseInstructions>
When using a tool, follow the JSON schema carefully and ensure all required parameters are provided...
</toolUseInstructions>
|
🌍 上下文类标签
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<environment_info>
<UserOSPrompt />
<UserShellPrompt />
</environment_info>
<workspace_info>
<WorkspaceFoldersHint />
<MultirootWorkspaceStructure maxSize={2000} />
</workspace_info>
<context>
<CurrentDatePrompt />
<EditedFileEvents />
<TerminalState />
</context>
|
📝 用户请求标签
1
2
3
4
5
6
7
8
|
<userRequest priority={900}>
{query + attachmentHint}
</userRequest>
<reminderInstructions>
{getKeepGoingReminder(modelFamily)}
{getEditingReminder(hasEditTool, hasReplaceStringTool)}
</reminderInstructions>
|
2.3 动态标签生成
1
2
3
4
5
6
7
8
9
10
|
// 根据可用工具动态调整提示词内容
const hasReadFileTool = !!availableTools?.find(tool => tool.name === 'readFile');
const hasTerminalTool = !!availableTools?.find(tool => tool.name === 'runInTerminal');
return (
<toolUseInstructions>
{hasReadFileTool && <>When using the readFile tool, prefer reading large sections...</>}
{hasTerminalTool && <>NEVER print terminal commands, use the runInTerminal tool instead...</>}
</toolUseInstructions>
);
|
2.4 Tag标签的优势
优势 |
说明 |
示例 |
结构清晰 |
内容分类明确,AI理解更准确 |
<instructions> vs <context> |
语义明确 |
标签名直接表达内容用途 |
<userRequest> vs <examples> |
易于解析 |
AI模型对XML标签理解更好 |
比纯文本准确率高20-30% |
可组合性 |
支持嵌套和模块化组织 |
<context><currentFile>...</currentFile></context> |
3. 格式化输出:三种方法对比
3.1 方法一:纯提示词JSON
实现方式
1
2
3
4
5
6
7
8
|
const prompt = `
请按以下JSON格式返回结果:
{
"action": "create|edit|delete",
"filePath": "文件路径",
"content": "文件内容"
}
`;
|
常见问题
1
2
3
4
5
6
7
8
|
❌ AI经常返回:
```json
{
"action": "create",
"filePath": "/test.js"
// 突然停止或添加解释文字
}
我觉得这个文件还需要...
|
❌ 或者格式错误:
1
2
3
|
{
action: "create" // 缺少引号
"filePath": "/test.js", // 多余逗号
|
问题根源
- AI容易"发挥",添加额外内容
- JSON格式容错性差
- 复杂嵌套结构成功率低
- 解析失败后难以恢复
3.2 方法二:Tag标签结构化
实现方式
1
2
3
4
5
6
7
8
|
<outputFormat>
Always respond in this format:
<action>create|edit|delete</action>
<filePath>/path/to/file</filePath>
<content>
// 文件内容
</content>
</outputFormat>
|
解析示例
1
2
3
4
5
6
7
8
9
10
11
12
|
// 相对可靠的解析
function parseTagResponse(response) {
const actionMatch = response.match(/<action>(.*?)<\/action>/);
const pathMatch = response.match(/<filePath>(.*?)<\/filePath>/);
const contentMatch = response.match(/<content>(.*?)<\/content>/s);
return {
action: actionMatch?.[1],
filePath: pathMatch?.[1],
content: contentMatch?.[1]
};
}
|
优势与局限
- ✅ 比JSON更可靠(85-90%成功率)
- ✅ AI对标签理解更好
- ✅ 容错性较强
- ⚠️ 仍需手动解析
- ⚠️ 复杂嵌套时可能出错
3.3 方法三:Function Call
Schema定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
const toolSchema: vscode.LanguageModelToolInformation = {
name: 'editFile',
description: 'Edit a file with specific changes',
inputSchema: {
type: 'object',
required: ['filePath', 'action'],
properties: {
filePath: {
type: 'string',
description: '文件绝对路径'
},
action: {
type: 'string',
enum: ['create', 'edit', 'delete'],
description: '操作类型'
},
content: {
type: 'string',
description: '文件内容'
}
}
}
};
|
工具实现
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
|
class EditFileTool implements ICopilotTool<EditFileParams> {
async invoke(options: vscode.LanguageModelToolInvocationOptions<EditFileParams>) {
// 1. 自动验证输入参数(Schema强制约束)
const { filePath, action, content } = options.input;
// 2. 执行实际操作
switch (action) {
case 'create':
await this.fileSystem.writeFile(filePath, content);
break;
case 'edit':
await this.applyEdits(filePath, content);
break;
case 'delete':
await this.fileSystem.deleteFile(filePath);
break;
}
// 3. 返回结构化结果
return new LanguageModelToolResult([
new LanguageModelPromptTsxPart(
<EditResult
operation={action}
filePath={filePath}
success={true}
/>
)
]);
}
}
|
3.4 三种方法全面对比
维度 |
纯提示词JSON |
Tag标签方法 |
Function Call |
准确性 |
60-70% |
85-90% |
95-99% |
可靠性 |
⭐⭐ |
⭐⭐⭐⭐ |
⭐⭐⭐⭐⭐ |
复杂数据支持 |
❌ 差 |
⚠️ 中等 |
✅ 优秀 |
错误恢复 |
❌ 困难 |
⚠️ 一般 |
✅ 容易 |
实现复杂度 |
⭐ |
⭐⭐ |
⭐⭐⭐⭐ |
执行能力 |
❌ 无 |
❌ 无 |
✅ 直接执行 |
数据验证 |
❌ 手动 |
❌ 手动 |
✅ 自动 |
类型安全 |
❌ 无 |
❌ 无 |
✅ 强类型 |
4. Function Call:终极解决方案
4.1 核心架构
工具注册系统
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// 统一的工具注册机制
export const ToolRegistry = new class {
private _tools: ICopilotToolCtor[] = [];
public registerTool(tool: ICopilotToolCtor) {
this._tools.push(tool);
}
public getTools(): readonly ICopilotToolCtor[] {
return this._tools;
}
}();
// 注册工具
ToolRegistry.registerTool(ReadFileTool);
ToolRegistry.registerTool(CreateFileTool);
ToolRegistry.registerTool(EditFileTool);
|
接口标准化
1
2
3
4
5
6
7
8
9
10
11
12
13
|
interface ICopilotTool<T> extends vscode.LanguageModelTool<T> {
// 主执行方法
invoke(options: vscode.LanguageModelToolInvocationOptions<T>): Promise<vscode.LanguageModelToolResult>;
// 调用准备(显示进度等)
prepareInvocation?(options: vscode.LanguageModelToolInvocationPrepareOptions<T>): vscode.ProviderResult<vscode.PreparedToolInvocation>;
// 输入解析和验证
resolveInput?(input: T, promptContext: IBuildPromptContext): Promise<T>;
// 编辑确认过滤
filterEdits?(resource: URI): Promise<IEditFilterData | undefined>;
}
|
4.2 丰富的工具生态
vscode-copilot-chat项目包含40多个专业工具:
📁 文件操作工具
1
2
3
4
5
|
import './readFileTool'; // 读取文件内容
import './createFileTool'; // 创建新文件
import './replaceStringTool'; // 字符串替换
import './applyPatchTool'; // 应用代码补丁
import './listDirTool'; // 列出目录内容
|
🔍 搜索工具
1
2
3
4
|
import './findFilesTool'; // 查找文件
import './findTextInFilesTool'; // 文本搜索
import './searchWorkspaceSymbolsTool'; // 符号搜索
import './codebaseTool'; // 代码库语义搜索
|
🛠️ 开发工具
1
2
3
4
|
import './runTestsTool'; // 运行测试
import './runInTerminalTool'; // 终端命令执行
import './getErrorsTool'; // 获取错误信息
import './scmChangesTool'; // Git变更查看
|
📝 编辑工具
1
2
3
|
import './insertEditTool'; // 插入编辑
import './editNotebookTool'; // Notebook编辑
import './newWorkspaceTool'; // 创建工作区
|
4.3 高级特性
复杂数据结构支持
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
interface ComplexEditParams {
files: Array<{
path: string;
operation: 'create' | 'edit' | 'delete';
changes: Array<{
startLine: number;
endLine: number;
newContent: string;
reason: string;
}>;
metadata: {
language: string;
encoding: string;
backup: boolean;
};
}>;
batchOperation: {
transactional: boolean;
rollbackOnError: boolean;
confirmEachFile: boolean;
};
}
|
实时交互能力
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
async invoke(options: LanguageModelToolInvocationOptions<EditParams>) {
// 1. 显示进度
this.progressReporter.report({ message: 'Reading target file...' });
// 2. 执行操作
const result = await this.applyEdits(options.input);
// 3. 实时反馈
this.streamReporter.textEdit(uri, true);
// 4. 返回丰富结果
return new LanguageModelToolResult([
new LanguageModelPromptTsxPart(
<EditResult
files={result.modifiedFiles}
diagnostics={result.diagnostics}
suggestions={result.suggestions}
/>
)
]);
}
|
错误处理和恢复
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
try {
const result = await this.performEdit(params);
this.telemetryService.logSuccess('editFile', params);
return result;
} catch (error) {
// 详细错误分类
if (error instanceof FileNotFoundError) {
return new LanguageModelToolResult([
new LanguageModelTextPart(`File not found: ${params.filePath}. Use createFile tool instead.`)
]);
} else if (error instanceof PermissionError) {
return new LanguageModelToolResult([
new LanguageModelTextPart(`Permission denied. Please check file permissions.`)
]);
}
// 遥测和回退
this.telemetryService.logError('editFile', error, params);
throw error;
}
|
5. 完美组合:Tag + Function Call
5.1 架构设计
graph TB
A[用户请求] --> B[Tag标签构建提示词]
B --> C[AI理解结构化指令]
C --> D[Function Call执行操作]
D --> E[返回格式化结果]
B1[instructions标签] --> C
B2[context标签] --> C
B3[toolUseInstructions标签] --> C
D1[工具Schema验证] --> E
D2[实际操作执行] --> E
D3[结果结构化] --> E
5.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
|
// 使用Tag组织复杂提示词
<instructions>
You are a sophisticated coding assistant that helps developers with file operations.
</instructions>
<toolUseInstructions>
- Use readFile to understand existing code before making changes
- Use createFile for new files, editFile for modifications
- Always provide clear descriptions of your changes
- Group related operations together
</toolUseInstructions>
<context>
<currentWorkspace>{workspacePath}</currentWorkspace>
<activeFile>{activeFileName}</activeFile>
<recentChanges>{recentEditHistory}</recentChanges>
</context>
<availableTools>
{toolNames.map(name => `- ${name}: ${toolDescriptions[name]}`).join('\n')}
</availableTools>
<userRequest>
{userQuery}
</userRequest>
|
工具定义
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
39
40
41
42
43
44
|
// 精确的Schema定义
const editFileSchema: vscode.LanguageModelToolInformation = {
name: 'editFile',
description: 'Apply specific edits to an existing file',
inputSchema: {
type: 'object',
required: ['filePath', 'edits'],
properties: {
filePath: {
type: 'string',
description: 'Absolute path to the file to edit'
},
description: {
type: 'string',
description: 'Brief description of what changes are being made (max 100 chars)',
maxLength: 100
},
edits: {
type: 'array',
description: 'Array of specific edits to apply',
items: {
type: 'object',
required: ['startLine', 'endLine', 'newContent'],
properties: {
startLine: {
type: 'number',
minimum: 1,
description: '1-based line number where edit starts'
},
endLine: {
type: 'number',
minimum: 1,
description: '1-based line number where edit ends (inclusive)'
},
newContent: {
type: 'string',
description: 'New content to replace the specified lines'
}
}
}
}
}
}
};
|
工具实现
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
39
40
|
class EditFileTool implements ICopilotTool<EditFileParams> {
async invoke(options: vscode.LanguageModelToolInvocationOptions<EditFileParams>) {
const { filePath, description, edits } = options.input;
// 1. 验证和准备
const uri = this.resolveFilePath(filePath);
const document = await this.loadDocument(uri);
// 2. 应用编辑
const results = [];
for (const edit of edits) {
const result = await this.applyEdit(document, edit);
results.push(result);
}
// 3. 保存和反馈
await this.saveDocument(document);
this.notifyEditorOfChanges(uri);
// 4. 返回结构化结果
return new LanguageModelToolResult([
new LanguageModelPromptTsxPart(
<EditSummary
filePath={filePath}
description={description}
editsApplied={results.length}
success={true}
details={results}
/>
)
]);
}
async prepareInvocation(options: vscode.LanguageModelToolInvocationPrepareOptions<EditFileParams>) {
return {
invocationMessage: new MarkdownString(`✏️ Editing ${this.getFileName(options.input.filePath)}...`),
pastTenseMessage: new MarkdownString(`✅ Edited ${this.getFileName(options.input.filePath)}`)
};
}
}
|
5.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
39
40
41
42
|
// 完整的交互流程
async function handleUserRequest(query: string) {
// 1. 构建结构化提示词
const prompt = (
<instructions>
You are a coding assistant. Use the available tools to help the user.
</instructions>
<toolUseInstructions>
- Read files before editing them
- Provide clear descriptions of changes
- Use appropriate tools for each task
</toolUseInstructions>
<context>
<workspace>{getCurrentWorkspace()}</workspace>
<activeFiles>{getActiveFiles()}</activeFiles>
</context>
<userRequest>
{query}
</userRequest>
);
// 2. AI调用工具
const response = await languageModel.sendRequest(prompt, {
tools: [readFileSchema, editFileSchema, createFileSchema]
});
// 3. 处理工具调用
for (const toolCall of response.toolCalls) {
const tool = getToolByName(toolCall.name);
const result = await tool.invoke({
input: toolCall.parameters,
model: response.model,
chatRequestId: generateId()
});
// 4. 展示结果
displayToolResult(result);
}
}
|
6. 实战案例分析
6.1 案例:智能代码重构
用户请求
“帮我重构这个React组件,将类组件改为函数组件,并使用hooks”
Tag标签提示词
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
|
<instructions>
You are an expert React developer. Help refactor the code using modern React patterns.
</instructions>
<refactoringRules>
- Convert class components to function components
- Replace lifecycle methods with appropriate hooks
- Maintain the same functionality and props interface
- Use TypeScript if the original code uses it
- Add proper error boundaries if needed
</refactoringRules>
<context>
<currentFile>{currentComponentCode}</currentFile>
<dependencies>{packageJsonDependencies}</dependencies>
<tsConfig>{typeScriptConfig}</tsConfig>
</context>
<availableTools>
- readFile: Read the current component file
- editFile: Apply the refactored code
- runTests: Verify the refactoring doesn't break tests
</availableTools>
<userRequest>
{userQuery}
</userRequest>
|
Function Call执行
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
|
// AI会调用这些工具
1. readFile({ filePath: '/src/components/UserProfile.tsx' })
2. editFile({
filePath: '/src/components/UserProfile.tsx',
description: 'Convert class component to function component with hooks',
edits: [
{
startLine: 1,
endLine: 50,
newContent: `import React, { useState, useEffect } from 'react';
import { User } from '../types/User';
interface UserProfileProps {
userId: string;
onUserUpdate: (user: User) => void;
}
const UserProfile: React.FC<UserProfileProps> = ({ userId, onUserUpdate }) => {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchUser(userId).then(userData => {
setUser(userData);
setLoading(false);
});
}, [userId]);
// ... rest of component
};
export default UserProfile;`,
reason: 'Convert class component to functional component with hooks'
}
]
})
3. runTests({ testPattern: '**/UserProfile.test.tsx' })
|
6.2 案例:API集成开发
用户请求
“创建一个用户管理API,包含CRUD操作和数据验证”
结构化实现
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
// 1. Tag构建的指导提示
<instructions>
Create a robust user management API with proper error handling and validation.
</instructions>
<apiRequirements>
- RESTful endpoints for CRUD operations
- Input validation using Joi or similar
- Proper HTTP status codes
- Error handling middleware
- Database integration with Prisma/Mongoose
- Authentication middleware
</apiRequirements>
<context>
<existingFiles>{currentApiStructure}</existingFiles>
<databaseSchema>{userSchema}</databaseSchema>
<framework>Express.js with TypeScript</framework>
</context>
// 2. Function Call执行多个工具
const toolCalls = [
{
name: 'createFile',
parameters: {
filePath: '/src/routes/users.ts',
content: `// User routes with full CRUD operations
import express from 'express';
import { UserController } from '../controllers/UserController';
import { validateUser } from '../middleware/validation';
import { authenticate } from '../middleware/auth';
const router = express.Router();
const userController = new UserController();
router.get('/', authenticate, userController.getAllUsers);
router.get('/:id', authenticate, userController.getUserById);
router.post('/', authenticate, validateUser, userController.createUser);
router.put('/:id', authenticate, validateUser, userController.updateUser);
router.delete('/:id', authenticate, userController.deleteUser);
export default router;`
}
},
{
name: 'createFile',
parameters: {
filePath: '/src/controllers/UserController.ts',
content: `// User controller with business logic and error handling
// ... implementation`
}
}
];
|
7. 最佳实践指南
7.1 何时使用哪种方法
选择决策树
graph TD
Start[需要AI输出格式化内容] --> NeedExecution{需要执行操作?}
NeedExecution -->|是| UseTools[使用Function Call]
NeedExecution -->|否| CheckComplexity{数据结构复杂?}
CheckComplexity -->|复杂| UseTools
CheckComplexity -->|简单| CheckReliability{可靠性要求高?}
CheckReliability -->|高| UseTags[使用Tag标签]
CheckReliability -->|一般| UseJSON[纯提示词JSON]
UseTools --> Implementation[工具实现 + Schema验证]
UseTags --> TagImplementation[Tag标签 + 正则解析]
UseJSON --> JSONImplementation[提示词约束 + 手动解析]
具体场景推荐
场景 |
推荐方法 |
原因 |
文件操作 |
Function Call |
需要实际执行+可靠性要求极高 |
代码生成 |
Function Call |
复杂结构+需要语法验证 |
数据分析 |
Tag标签 |
结构化输出但不需要执行 |
简单分类 |
Tag标签 |
相对简单但需要可靠性 |
实验原型 |
JSON提示词 |
快速测试,对准确性要求不高 |
7.2 Tag标签最佳实践
命名规范
1
2
3
4
5
6
7
8
9
10
11
|
// ✅ 好的标签命名
<instructions> // 清晰的功能指示
<toolUseInstructions> // 具体的使用说明
<context> // 上下文信息
<userRequest> // 用户输入
<outputFormat> // 输出格式要求
// ❌ 避免的命名
<info> // 太模糊
<stuff> // 无意义
<data> // 不具体
|
层次结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// ✅ 清晰的层次结构
<context>
<environment>
<operatingSystem>{os}</operatingSystem>
<shell>{shell}</shell>
</environment>
<workspace>
<rootPath>{workspaceRoot}</rootPath>
<activeFiles>{activeFiles}</activeFiles>
</workspace>
<userPreferences>
<codeStyle>{codeStyle}</codeStyle>
<framework>{preferredFramework}</framework>
</userPreferences>
</context>
|
内容组织
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
// ✅ 逻辑分组
<instructions>
You are a coding assistant specialized in web development.
</instructions>
<capabilities>
- Create and edit files
- Run terminal commands
- Search codebase
- Generate tests
</capabilities>
<limitations>
- Cannot access external APIs without tools
- Cannot modify system settings
- Must follow security guidelines
</limitations>
<behaviorRules>
- Always explain your reasoning
- Ask for clarification when uncertain
- Provide multiple solutions when appropriate
</behaviorRules>
|
7.3 Function Call高级技巧
Schema设计原则
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
39
40
41
42
43
44
45
46
|
// ✅ 详细的Schema设计
const toolSchema = {
name: 'editFile',
description: 'Edit an existing file with specific changes. Use this for modifications to existing code.',
inputSchema: {
type: 'object',
required: ['filePath', 'edits'],
properties: {
filePath: {
type: 'string',
description: 'Absolute path to the file (use forward slashes)',
pattern: '^/.*' // 路径验证
},
description: {
type: 'string',
description: 'Brief summary of what changes are being made (max 100 chars)',
maxLength: 100
},
edits: {
type: 'array',
minItems: 1,
maxItems: 20, // 防止过大的编辑
items: {
type: 'object',
required: ['startLine', 'endLine', 'newContent'],
properties: {
startLine: {
type: 'integer',
minimum: 1,
description: '1-based line number where edit starts'
},
endLine: {
type: 'integer',
minimum: 1,
description: '1-based line number where edit ends (inclusive)'
},
newContent: {
type: 'string',
description: 'New content to replace the specified lines'
}
}
}
}
}
}
};
|
错误处理策略
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
39
40
41
|
class RobustTool implements ICopilotTool<ToolParams> {
async invoke(options: LanguageModelToolInvocationOptions<ToolParams>) {
try {
// 预验证
this.validateInput(options.input);
// 执行操作
const result = await this.performOperation(options.input);
// 成功遥测
this.logSuccess(options);
return new LanguageModelToolResult([
new LanguageModelPromptTsxPart(<SuccessResult {...result} />)
]);
} catch (error) {
// 分类错误处理
if (error instanceof ValidationError) {
return new LanguageModelToolResult([
new LanguageModelTextPart(`❌ Input validation failed: ${error.message}`)
]);
} else if (error instanceof FileSystemError) {
return new LanguageModelToolResult([
new LanguageModelTextPart(`📁 File system error: ${error.message}. Please check file permissions.`)
]);
} else {
// 记录未知错误
this.logError(error, options);
throw error; // 让系统处理
}
}
}
private validateInput(input: ToolParams) {
if (!input.filePath || !input.filePath.startsWith('/')) {
throw new ValidationError('filePath must be an absolute path starting with /');
}
// 更多验证...
}
}
|
性能优化
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
39
40
41
|
// 批量操作支持
interface BatchEditParams {
operations: Array<{
type: 'create' | 'edit' | 'delete';
filePath: string;
content?: string;
edits?: EditOperation[];
}>;
transactional: boolean; // 是否事务性执行
}
class BatchEditTool implements ICopilotTool<BatchEditParams> {
async invoke(options: LanguageModelToolInvocationOptions<BatchEditParams>) {
const { operations, transactional } = options.input;
if (transactional) {
// 事务性执行:全部成功或全部回滚
return await this.executeTransactional(operations);
} else {
// 并行执行,提高性能
return await this.executeParallel(operations);
}
}
private async executeParallel(operations: BatchEditParams['operations']) {
const results = await Promise.allSettled(
operations.map(op => this.executeOperation(op))
);
return new LanguageModelToolResult([
new LanguageModelPromptTsxPart(
<BatchResult
totalOperations={operations.length}
successful={results.filter(r => r.status === 'fulfilled').length}
failed={results.filter(r => r.status === 'rejected').length}
details={results}
/>
)
]);
}
}
|
7.4 组合使用的高级模式
自适应工具选择
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
39
40
41
42
43
44
45
46
47
|
// 根据上下文动态调整可用工具
const AdaptivePrompt = ({ userQuery, workspaceType, userSkillLevel }) => {
const availableTools = selectToolsForContext(workspaceType, userSkillLevel);
return (
<instructions>
You are a coding assistant adapted for {workspaceType} development.
User skill level: {userSkillLevel}
</instructions>
<toolsContext>
Available tools for this session:
{availableTools.map(tool =>
`- ${tool.name}: ${tool.description}`
).join('\n')}
</toolsContext>
<adaptiveRules>
{userSkillLevel === 'beginner' &&
'Provide detailed explanations and suggest best practices.'
}
{userSkillLevel === 'expert' &&
'Focus on efficiency and advanced techniques.'
}
</adaptiveRules>
<userRequest>
{userQuery}
</userRequest>
);
};
function selectToolsForContext(workspaceType: string, skillLevel: string) {
const baseTools = ['readFile', 'editFile', 'createFile'];
if (workspaceType === 'react') {
baseTools.push('generateComponent', 'runTests', 'bundleAnalyzer');
} else if (workspaceType === 'python') {
baseTools.push('runPython', 'installPackage', 'lintCode');
}
if (skillLevel === 'expert') {
baseTools.push('refactorCode', 'performanceProfiling', 'securityAnalysis');
}
return baseTools.map(name => ToolRegistry.getTool(name));
}
|
工具链组合
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
39
40
41
42
43
44
45
46
47
|
// 复杂任务的工具链编排
class WorkflowOrchestrator {
async executeWorkflow(userRequest: string, context: WorkspaceContext) {
const workflow = this.planWorkflow(userRequest, context);
for (const step of workflow.steps) {
const stepResult = await this.executeStep(step);
// 根据步骤结果调整后续步骤
workflow.adjustRemainingSteps(stepResult);
// 向用户报告进度
this.reportProgress(step, stepResult);
}
return workflow.getFinalResult();
}
private planWorkflow(request: string, context: WorkspaceContext): Workflow {
// 使用Tag标签构建规划提示
const planningPrompt = (
<planningInstructions>
Analyze the user request and create a step-by-step plan.
Consider the current workspace context and available tools.
</planningInstructions>
<availableTools>
{this.getAvailableTools().map(tool => tool.description)}
</availableTools>
<workspaceContext>
{JSON.stringify(context, null, 2)}
</workspaceContext>
<userRequest>
{request}
</userRequest>
<outputFormat>
Return a JSON plan with steps, dependencies, and tool assignments.
</outputFormat>
);
// AI生成执行计划,然后使用Function Call执行
return this.generateWorkflowPlan(planningPrompt);
}
}
|
📚 结论
通过对vscode-copilot-chat项目的深度分析,我们发现了现代AI助手的最佳架构模式:
🎯 核心要点
- Tag标签用于构建提示词 - 提供结构化、易理解的指令框架
- Function Call用于格式化输出 - 确保可靠、可执行的结构化响应
- 两者完美结合 - 发挥各自优势,构建强大的AI助手系统
🚀 实施建议
阶段 |
方法 |
重点 |
原型开发 |
Tag标签 + 简单JSON |
快速验证想法 |
功能开发 |
Tag标签 + Function Call |
平衡可靠性和复杂性 |
生产部署 |
完整Function Call生态 |
最高可靠性和功能完整性 |
🔮 未来趋势
随着AI模型能力的不断提升,我们预期:
- Function Call将成为标准的AI交互模式
- 工具生态将更加丰富和专业化
- 多模态工具调用将成为可能
- 自适应工具选择将更加智能
这套方法论不仅适用于编程助手,也可以扩展到各种需要结构化输出和可靠执行的AI应用场景中。