Please enable Javascript to view the contents

Ai提示词工程与格式化输出最佳实践

 ·  ☕ 12 分钟

基于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助手的最佳架构模式:

🎯 核心要点

  1. Tag标签用于构建提示词 - 提供结构化、易理解的指令框架
  2. Function Call用于格式化输出 - 确保可靠、可执行的结构化响应
  3. 两者完美结合 - 发挥各自优势,构建强大的AI助手系统

🚀 实施建议

阶段 方法 重点
原型开发 Tag标签 + 简单JSON 快速验证想法
功能开发 Tag标签 + Function Call 平衡可靠性和复杂性
生产部署 完整Function Call生态 最高可靠性和功能完整性

🔮 未来趋势

随着AI模型能力的不断提升,我们预期:

  • Function Call将成为标准的AI交互模式
  • 工具生态将更加丰富和专业化
  • 多模态工具调用将成为可能
  • 自适应工具选择将更加智能

这套方法论不仅适用于编程助手,也可以扩展到各种需要结构化输出和可靠执行的AI应用场景中。


分享

Llane00
作者
Llane00
Web Developer