.NET+AI | MEAI | 提示工程基础(2)

MEAI 提示工程实战:从零构建企业级意图识别系统

一句话简介

本文以铁路票务意图识别为例,演示如何使用 Microsoft.Extensions.AI (MEAI) 构建高质量提示词,掌握 7 大核心技巧和参数调优方法,快速构建企业级 AI 应用。


🎯 核心价值

  • 结构化提示:掌握指令、上下文、输入、输出四大组件
  • 7 大核心技巧:从基础到进阶,系统提升提示词质量
  • MEAI 集成:使用 ChatOptions 和 ChatMessage 构建企业级管道
  • 参数调优:掌握 Temperature、TopP 等关键参数的最佳实践
  • 提示优化闭环:建立持续改进机制

📚 提示词基础框架

提示词由四大基础组件构成,缺一不可:

四大组件详解

组件 作用 示例
指令 明确任务目标 "识别用户的铁路票务意图"
上下文 提供背景知识 "可选意图包括:订票、退票、咨询"
输入 描述数据结构 "用户请求:帮我订一张票"
输出 约束响应格式 "以 JSON 格式返回 {intention, reason}"

为什么需要结构化?

  • ✅ 减少歧义,让模型理解任务边界
  • ✅ 提升准确性,帮助模型做出正确判断
  • ✅ 便于解析,让业务系统能够直接消费
  • ✅ 可维护性强,便于团队协作和迭代

🎬 场景设定:铁路票务意图识别

业务需求:识别用户属于以下哪一类意图,路由到对应的业务模块:

  • 🎫 订票意图:购买车票
  • 🔄 退票意图:退订车票
  • 咨询意图:咨询信息或无法明确判断

测试用例"帮我订一张从北京到上海的票,后天下午出发。"


💻 七大核心技巧演练

技巧一:明确任务边界 🎯

问题:基础提示容易导致模型输出冗余文字或答非所问。

解决:明确告诉模型"做什么"和"不做什么"。

基线提示(仅包含任务和输入):

csharp 复制代码
var baselinePrompt = $"""
请帮我识别用户意图。
用户请求是:{userRequest}
意图:
""";

技巧二:结构化输出 📊

问题:自然语言描述不便于程序解析。

解决:通过 JSON 结构约束回复,减少闲聊,让下游服务直接解析字段。

csharp 复制代码
var structuredPrompt = $$"""
你需要识别用户的铁路票务意图,选项仅包括:
* 订票意图
* 退票意图
* 咨询意图

请严格以如下 JSON 格式返回结果:
{
    "intention": "<订票意图/退票意图/咨询意图>",
    "reason": "<简要说明识别理由>"
}

用户请求:{{userRequest}}
""";

优势

  • ✅ 输出格式统一,便于自动化处理
  • ✅ 减少模型的冗余输出
  • ✅ 提高业务系统的集成效率

技巧三:少样本学习(Few-Shot)📚

问题:模型对边界情况判断不准确。

解决:加入 1-2 个高质量示例显著提升准确率。

csharp 复制代码
var fewShotPrompt = $$"""
你需要识别用户的铁路票务意图,选项仅包括:
* 订票意图
* 退票意图
* 咨询意图

<example>
用户请求:我的票能退吗?
意图:
{
    "intention": "退票意图",
    "reason": "用户询问是否可以退票"
}
</example>

<example>
用户请求:请问高铁可以带宠物吗?
意图:
{
    "intention": "咨询意图",
    "reason": "用户咨询乘车规则,非订退票"
}
</example>

用户请求:{{userRequest}}
""";

原理:通过示例让模型学习任务的"模式",类似于"通过例子教学"。


技巧四:角色设定(Role Prompting)👤

问题:模型缺乏明确的身份定位,输出风格不统一。

解决:通过 System 消息注入角色定义,提前锁定模型身份与口吻。

MEAI 实现方式 :使用 ChatMessage 列表,第一条设置为 ChatRole.System

csharp 复制代码
var rolePrompt = """
你是一名铁路票务意图识别专家,负责在前端界面与后端服务之间准确判断用户意图。
仅从以下选项中选择:订票意图、退票意图、咨询意图。

请严格以如下 JSON 格式返回结果:
{
    "intention": "<订票意图/退票意图/咨询意图>",
    "reason": "<简要说明识别理由>"
}

若无法明确判断,则选择 "咨询意图",理由写 "输入不够明确,默认为咨询"。
""";

var messages = new List<ChatMessage>
{
    new(ChatRole.System, rolePrompt),
    new(ChatRole.User, userRequest)
};

优势

  • ✅ 让模型"扮演"专业角色,输出更专业
  • ✅ 减少多轮对话中的风格漂移
  • ✅ 提高输出的一致性和可预测性

技巧五:添加上下文(Context Enrichment)🌐

问题:模型缺乏必要的业务上下文(如当前时间、用户信息等)。

解决:系统级上下文携带时间、用户信息等关键字段。

csharp 复制代码
var contextualPrompt = """
你是一名铁路票务意图识别专家,负责准确判断用户意图。

<context>
系统当前时间:2025年10月29日 18:00
用户Id:shengjie
用户等级:VIP会员
</context>

请严格以如下 JSON 格式返回结果:
{
    "intention": "<订票意图/退票意图/咨询意图>",
    "reason": "<简要说明识别理由>"
}
""";

应用场景

  • 🕒 时间相关任务(如"明天""后天"需要知道当前时间)
  • 👤 用户个性化(如根据用户历史行为调整回复)
  • 📍 业务规则(如特定时段的票务政策)

技巧六:拒答策略(Refusal Strategy)🛡️

问题:输入信息不足或超出范围时,模型可能"一本正经地胡说"。

解决:明确拒答与默认策略,在缺乏信息时选择最安全的响应。

csharp 复制代码
var refusalPrompt = """
你是一名铁路票务意图识别专家,负责判断用户是否在处理车票相关需求。

若无法判断为订票或退票,请返回咨询意图,并在 reason 中注明 "输入不涉及票务,默认为咨询"。
当完全没有票务相关线索时,请回复:
{
    "intention": "咨询意图",
    "reason": "输入不够明确,默认为咨询"
}
""";

拒答策略的价值

  • ✅ 降低幻觉风险
  • ✅ 提供回退机制
  • ✅ 提高系统鲁棒性

技巧七:思维链引导(Chain-of-Thought)🧠

问题:对于多步骤推理任务,模型可能直接给出结论,缺乏推理过程。

解决:给出思考流程提示,帮助模型逐条检查条件并给出稳健答案。

csharp 复制代码
var reasoningPrompt = """
你是一名铁路票务意图识别专家,负责分析用户文本并输出结构化结果。

当接收到输入时,请按以下步骤思考:
1. 关键词扫描:检查是否包含订票相关词,如"买票""预订""订"。
2. 退票检测:若无订票相关词,再查找"退票""取消""退"。
3. 咨询判断:若前两步未命中,判断是否属于咨询或闲聊。
4. 置信度评估:若不确定,选择咨询意图并在 reason 中说明原因。
5. 格式输出:严格按 JSON 模板返回结果。

请严格以如下 JSON 格式返回结果:
{
    "intention": "<订票意图/退票意图/咨询意图>",
    "reason": "<简要说明识别理由和推理过程>"
}
""";

思维链的价值

  • 🧩 提高复杂任务的准确性
  • 🧩 让推理过程可解释
  • 🧩 便于调试和优化

⚙️ MEAI 生成参数配置

在 MEAI 中,通过 ChatOptions 统一管理生成参数:

csharp 复制代码
var chatOptions = new ChatOptions
{
    Temperature = 0.1f,      // 低随机性,保证稳定输出
    TopP = 0.9f,             // 核采样
    MaxOutputTokens = 120    // 限制输出长度
};

var response = await chatClient.GetResponseAsync(userPrompt, chatOptions);

参数速查表

任务类型 Temperature TopP MaxTokens 说明
意图识别/分类 0.1-0.3 0.9 100-200 需要稳定输出
内容生成/创作 0.7-1.0 0.9 500-2000 需要创造性
摘要/提取 0.3-0.5 0.8 200-500 平衡准确性
代码生成 0.2-0.4 0.95 500-1500 语法准确
对话/闲聊 0.6-0.9 0.9 100-300 自然流畅

关键参数说明:

  • Temperature:控制随机性(0=确定性,2=高随机性)
  • TopP:核采样概率(0.9=保留90%概率质量)
  • MaxOutputTokens:限制输出长度,节省token成本

🔄 提示优化闭环

当基础提示稳定后,可借助模型本身迭代提示,形成"生成 → 评估 → 再生成"的循环。

让模型充当提示工程师:

csharp 复制代码
var improvementRequest = $"""
你是一名提示工程师,专注于提升提示词的清晰度和执行效果。
请分析以下提示词,并给出优化建议。

请按以下格式输出:
1. **优化后提示**:给出改进后的完整提示词
2. **改进说明**:说明做了哪些改进以及为什么
3. **进一步建议**:列出 2-3 条可选的进一步优化思路

待优化的原始提示如下:
{原始提示}
""";

🎯 总结

通过本文,我们系统学习了使用 MEAI 进行提示工程的核心技巧:

  • 四大基础组件:指令、上下文、输入、输出缺一不可
  • 七大核心技巧:从明确边界到思维链,逐步提升提示词质量
  • MEAI 集成:使用 ChatOptions 和 ChatMessage 构建企业级管道
  • 参数调优:Temperature、TopP、MaxOutputTokens 的最佳实践
  • 优化闭环:建立持续改进机制,让模型自我优化提示词

核心价值:

  • 🎯 提升输出质量:稳定、准确的输出
  • 🎯 便于系统集成:JSON 格式便于业务系统解析
  • 🎯 降低幻觉风险:拒答策略和思维链减少错误判断
  • 🎯 提高可维护性:清晰的提示结构便于团队协作

如需获取文章配套完整代码,可扫码咨询领取。👇