学会"问问题",让 AI 输出质量提升 10 倍!
前置知识
在开始之前,我们需要掌握以下技能:
- 基础 JavaScript/TypeScript:能看懂 async/await 即可
- LangChain 基础:了解 ChatOpenAI 和 PromptTemplate 的基本用法
- Node.js 环境:已安装 Node.js 18+ 版本
如果对 LangChain 环境搭建还不熟悉,建议先看我之前的文章《LangChain JS 入门:前端快速搭建 AI 开发环境》。
为什么提示词工程如此重要?
很多人觉得 AI "不够聪明",其实往往是我们"问得不够好"。同样的模型,提示词的质量直接决定输出的质量。
| 提示词类型 | 示例 | 效果 |
|---|---|---|
| ❌ 糟糕提示词 | "帮我写个登录页面" | 输出随意,风格不一致,可能缺少关键功能 |
| ✅ 优质提示词 | "用 Vue3 + TypeScript 写一个登录页,包含邮箱/手机号验证、记住密码功能,样式用 Tailwind CSS" | 输出精准,符合技术栈要求,功能完整 |
核心观点:提示词工程不是魔法,而是一套可学习、可复用的方法论。
优质提示词的核心编写原则
原则一:清晰明确
AI 无法读取你的想法,提示词越清晰,输出越精准。
text
❌ 模糊版:"帮我解释一下响应式"
✅ 清晰版:"用前端开发者的视角,解释 Vue3 的响应式原理,包含 Proxy 的使用,300字以内"
原则二:角色设定
给 AI 一个身份,它能更好地进入角色。
typescript
// 角色设定模板
const rolePrompt = `你是一个资深的前端架构师,有 8 年大厂经验。
擅长技术选型、代码规范制定和性能优化。
回答要专业但易懂,可以适当举例说明。`;
原则三:具体输出格式
指定输出格式,让结果可预测、可解析。
text
请按以下 JSON 格式输出:
{
"bugType": "类型(语法错误/逻辑错误/性能问题)",
"cause": "可能原因",
"solution": "解决方案",
"codeExample": "修复后的代码示例(如果需要)"
}
原则四:场景化约束
结合具体场景,给 AI 更精准的限制。
| 约束维度 | 示例 |
|---|---|
| 长度约束 | 回复不超过 200 字 |
| 风格约束 | 面向初级开发者,通俗易懂 |
| 技术栈约束 | 只使用 Vue3 Composition API,不使用 Options API |
| 禁止项 | 不要使用 any 类型,不要忽略错误处理 |
LangChain PromptTemplate 使用详解
基础语法
PromptTemplate 是 LangChain 中最基础的提示词模板组件,使用 {变量名} 作为占位符。
typescript
import { PromptTemplate } from "@langchain/core/prompts";
// 基础用法
const simpleTemplate = PromptTemplate.fromTemplate(
"你是一个{role},请用{style}的风格回答:{question}"
);
const formatted = await simpleTemplate.format({
role: "前端技术专家",
style: "幽默风趣",
question: "解释一下闭包"
});
console.log(formatted);
// 输出:你是一个前端技术专家,请用幽默风趣的风格回答:解释一下闭包
多变量与默认值
typescript
import { PromptTemplate } from "@langchain/core/prompts";
const template = new PromptTemplate({
inputVariables: ["bug", "lang"],
template: `你是一个前端代码审查专家。
【Bug描述】:{bug}
【目标语言】:{lang}
请完成以下任务:
1. 分析 Bug 原因(用 {lang} 回复)
2. 提供修复方案
3. 给出修复后的代码示例
注意:如果没有明确要求,默认使用 JavaScript。`,
// 可以为变量设置默认值(需要配合 partial 使用)
});
// 部分填充(预置默认值)
const partialTemplate = await template.partial({
lang: "TypeScript"
});
对话模板 ChatPromptTemplate
适用于多轮对话场景,支持 system、human、ai 等角色。
typescript
import { ChatPromptTemplate } from "@langchain/core/prompts";
const chatPrompt = ChatPromptTemplate.fromMessages([
["system", "你是一个{role},回答要{style},不超过{maxLength}字。"],
["human", "{question}"],
["ai", "好的,我正在思考..."],
["human", "请直接给出答案,不要废话"]
]);
const formatted = await chatPrompt.format({
role: "前端 bug 排查专家",
style: "简洁明了",
maxLength: "100",
question: "Vue3 中 ref 和 reactive 有什么区别?"
});
Few-Shot 示例提示词实战
Few-Shot(少样本学习)是通过提供几个示例,让模型理解你的期望输出格式和风格。
场景:前端代码生成
typescript
import { ChatOpenAI } from "@langchain/openai";
import { SystemMessage, HumanMessage } from "@langchain/core/messages";
import dotenv from "dotenv";
dotenv.config();
async function fewShotDemo() {
// 1. 定义 Few-Shot 示例
const examples = [
{
input: "写一个函数,判断是否为回文数",
output: `/**
* 判断一个整数是否为回文数
* @param {number} x - 待判断的整数
* @returns {boolean} - 是回文数返回 true,否则返回 false
*/
function isPalindrome(x: number): boolean {
if (x < 0) return false;
const str = x.toString();
return str === str.split('').reverse().join('');
}`
},
{
input: "写一个函数,实现防抖",
output: `/**
* 防抖函数
* @param {Function} fn - 需要防抖的函数
* @param {number} delay - 延迟时间(毫秒)
* @returns {Function} - 防抖后的函数
*/
function debounce<T extends (...args: any[]) => any>(
fn: T,
delay: number
): (...args: Parameters<T>) => void {
let timer: NodeJS.Timeout;
return (...args: Parameters<T>) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
}`
}
];
// 2. 手动构建示例文本
const formattedExamples = examples.map(ex =>
`用户需求:${ex.input}\n代码输出:\n${ex.output}`
).join("\n\n");
// 3. 构建消息
const systemPrompt = `你是一个资深前端工程师,擅长编写高质量、有注释的 TypeScript 代码。
以下是几个优秀的代码示例,请参考它们的风格:
${formattedExamples}
要求:
- 必须有 JSDoc 注释
- 使用 TypeScript 类型
- 考虑边界情况
- 代码风格保持一致`;
const userPrompt = "写一个函数,实现数组去重(支持对象数组根据指定字段去重)";
// 4. 调用模型
const model = new ChatOpenAI({
apiKey: process.env.DASHSCOPE_API_KEY,
configuration: {
baseURL: process.env.DASHSCOPE_API_URL,
},
model: "qwen-turbo",
temperature: 0.3,
});
const messages = [
new SystemMessage(systemPrompt),
new HumanMessage(userPrompt)
];
const response = await model.invoke(messages);
console.log("生成的代码:\n");
console.log(response.content);
}
fewShotDemo();
国内模型提示词优化技巧
技巧一:中文优先,避免中英混杂
text
❌ 避免:"Please write a function to 处理数组数据"
✅ 推荐:"请用 JavaScript 写一个函数,处理数组数据"
技巧二:控制提示词长度
阿里云百炼的 qwen-turbo 模型上下文窗口为 1M tokens,但提示词过长会影响响应速度。
typescript
// 将复杂提示词拆分为多个小提示词
const shortPrompts = [
"角色设定:你是一个前端专家",
"任务:分析以下代码的性能问题",
"代码:" + codeSnippet
];
// 或者使用精简表达
const concisePrompt = `【角色】前端专家 | 【任务】分析性能问题 | 【代码】${codeSnippet}`;
技巧三:使用分隔符结构化
typescript
const structuredPrompt = `
=== 角色设定 ===
你是一个严谨的前端代码审查专家
=== 输入代码 ===
\`\`\`typescript
${userCode}
\`\`\`
=== 输出要求 ===
请按以下格式输出:
1. 严重程度:【高/中/低】
2. 问题描述:【具体问题】
3. 修复建议:【方案】
4. 优化后代码:【代码示例】
=== 注意事项 ===
- 不要输出多余的解释
- 优先关注性能和安全问题
`;
实战:前端 Bug 排查助手
完整代码实现
创建 src/bug-assistant.ts:
typescript
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { ChatOpenAI } from "@langchain/openai";
import dotenv from "dotenv";
dotenv.config();
async function bugAssistant() {
// 定义系统提示词 - 转义 JSON 中的花括号
const systemPrompt = `你是一个专业的前端 Bug 排查助手。
【你的能力】
- 快速定位 JavaScript/TypeScript 代码中的问题
- 分析 Vue3 / React 框架相关的常见坑点
- 提供可执行的修复方案
【输出格式】
请严格按照以下 JSON 格式返回:
{{"bugType": "类型(语法错误/逻辑错误/性能问题/兼容性问题/框架使用错误)",
"severity": "严重程度(高/中/低)",
"rootCause": "根本原因分析(一句话概括)",
"solution": "解决方案(具体步骤)",
"fixedCode": "修复后的代码(如适用)",
"prevention": "如何避免类似问题"}}
【注意事项】
- 如果无法确定,请说明需要更多信息
- 不要猜测,基于代码本身分析
- 保持专业、简洁`;
// 定义用户提示词模板 - 使用转义的花括号
const userPromptTemplate = `
【Bug 描述】
{description}
【相关代码】
\`\`\`{lang}
{code}
\`\`\`
【错误信息(如有)】
{errorMsg}
【环境信息】
- 框架:{framework}
- 版本:{version}
`;
const prompt = ChatPromptTemplate.fromMessages([
["system", systemPrompt],
["human", userPromptTemplate]
]);
const model = new ChatOpenAI({
apiKey: process.env.DASHSCOPE_API_KEY,
configuration: {
baseURL: process.env.DASHSCOPE_API_URL,
},
model: "qwen-turbo",
temperature: 0.2, // Bug 排查需要准确,降低温度
});
const chain = prompt.pipe(model);
// 测试用例:Vue3 响应式丢失问题
const testCase = {
description: "修改 reactive 对象后,页面没有更新",
lang: "typescript",
code: `const state = reactive({ count: 0 });
function increment() {
// 这样做页面不会更新
state = { count: state.count + 1 };
}`,
errorMsg: "没有报错,但页面没反应",
framework: "Vue3",
version: "3.3.0"
};
console.log("🔍 正在分析 Bug...\n");
console.log(`【Bug 描述】${testCase.description}`);
console.log(`【代码】\n${testCase.code}\n`);
const response = await chain.invoke(testCase);
console.log("📋 分析结果:\n");
console.log(response.content);
// 尝试提取和解析 JSON
try {
// 从响应中提取 JSON 对象
const content = response.content as string;
const jsonMatch = content.match(/\{[\s\S]*\}/);
if (jsonMatch) {
const result = JSON.parse(jsonMatch[0]);
console.log("🔖 Bug 类型:", result.bugType);
console.log("⚠️ 严重程度:", result.severity);
console.log("🎯 根本原因:", result.rootCause);
console.log("💡 解决方案:", result.solution);
if (result.fixedCode) {
console.log("📝 修复代码:\n", result.fixedCode);
}
console.log("🛡️ 预防建议:", result.prevention);
} else {
// 如果不是 JSON 格式,直接输出
console.log(content);
}
} catch (error) {
console.error("JSON 解析失败,直接显示原始输出:");
console.log(response.content);
}
}
bugAssistant();
提示词效果对比:优化前 vs 优化后
对比测试
| 维度 | ❌ 优化前 | ✅ 优化后 |
|---|---|---|
| 提示词 | "帮我修复这个 bug" + 代码 | 结构化提示词(角色+格式+示例+约束) |
| 输出结构 | 随意段落,可能遗漏关键信息 | 固定 JSON 格式,包含 type/severity/solution/fixedCode |
| 代码质量 | 可能没有注释,类型不完整 | 有 JSDoc,使用 TypeScript,考虑边界情况 |
| 响应时间 | 较长(需要自己组织输出) | 更快(格式约束后生成效率高) |
| 可用率 | ~60%(需要人工二次处理) | ~95%(可直接解析使用) |
实际输出对比
优化前输出:
你的代码有问题,state 不能重新赋值,要用 state.count++ 来修改。建议了解一下 Vue3 的响应式原理...
优化后输出(JSON):
json
{
"bugType": "框架使用错误",
"severity": "高",
"rootCause": "reactive 对象被整体重新赋值,导致响应式连接丢失",
"solution": "直接修改对象属性,不要重新赋值整个对象",
"fixedCode": "const state = reactive({ count: 0 });\n\nfunction increment() {\n state.count++;\n}",
"prevention": "避免直接重新赋值 reactive 对象,而是修改其属性或使用 ref 来包装对象"
}
结语
提示词工程是 AI 应用开发中投入产出比最高的技能之一。掌握本文介绍的编写原则和 LangChain PromptTemplate 用法,你就能让 AI 输出质量提升 10 倍。
对于文章中错误的地方或有任何疑问,欢迎在评论区留言讨论!