1. 问题现象与背景解析
最近在Azure AI Search与大型语言模型(LLM)的集成实践中,不少开发者反馈遇到一个典型问题:当通过Azure Agent调用检索增强生成(RAG)流程时,系统返回的是原始JSON格式的文档引用,而非预期的LLM生成的归纳性答案。这种情况通常发生在构建知识库问答系统、智能客服或文档摘要等场景中。
我曾在三个企业级项目中亲历此问题,最典型的表现是:用户提问"如何配置Azure Blob存储的跨域访问?",系统返回的却是包含CORS设置片段的JSON文档数组,而非整理好的操作步骤说明。这种体验就像在图书馆查询时,管理员直接扔给你一堆书页而不是回答问题。
2. 核心原因深度剖析
2.1 检索-生成流程断点
问题的本质在于检索(RETRIEVE)与生成(GENERATE)两个阶段的衔接失效。正常流程应该是:
- 检索模块从Azure AI Search获取相关文档片段
- 将片段与用户问题拼接为LLM的输入prompt
- LLM生成自然语言响应
当出现JSON原始返回时,往往意味着:
- 流程在步骤1后直接返回了结果
- 步骤2的prompt组装环节缺失或异常
- LLM调用未被正确触发
2.2 Azure Agent配置关键点
在Azure AI Studio中创建Agent时,以下几个配置项直接影响该行为:
{ "retrieval": { "response_mode": "raw" | "processed", // 关键参数 "top_n": 5, "rerank": true }, "generation": { "temperature": 0.7, "max_tokens": 500 } }重要提示:当
response_mode设为"raw"时,系统会绕过LLM直接返回检索结果。这是大多数意外获取JSON数据的根源。
3. 完整解决方案与实操
3.1 配置修正方案
方案A:通过Azure Portal修改
- 导航至AI Studio > 你的Agent > 配置
- 在"检索设置"中找到"响应模式"
- 从"raw"改为"processed"
- 保存并重新部署Agent
方案B:通过API修正对于自动化部署场景,可通过PATCH请求更新配置:
import requests update_payload = { "retrieval": { "response_mode": "processed" } } response = requests.patch( "https://{your-endpoint}.openai.azure.com/agents/{agent-id}", headers={"api-key": "{your-key}"}, json=update_payload )3.2 自定义prompt模板
更精细的控制需要自定义prompt模板。以下是经过生产验证的模板:
# 上下文注入模板 你是一位专业的{{domain}}顾问。请基于以下知识库片段回答问题: 问题:{{query}} 相关文档: {% for doc in documents %} [片段{{loop.index}}]: {{doc.content}} {% endfor %} 请用中文组织答案,要求: 1. 直接解决问题,不要复述问题 2. 如文档不相关,回答"未找到相关信息" 3. 保持专业但易懂的风格在Azure AI Studio中配置路径: Agent > 高级设置 > Prompt模板 > 覆盖默认检索模板
4. 深度调试与验证
4.1 诊断流程图
当问题发生时,建议按以下步骤排查:
检查Agent日志中的
invocation记录- 确认是否触发了
llm.chat操作 - 查看输入prompt的组装情况
- 确认是否触发了
测试纯检索端点
POST https://{endpoint}/retrieve Body: {"query":"测试问题"}确认返回的是文档而非答案
验证LLM端点可用性
POST https://{endpoint}/chat Body: {"messages":[{"role":"user","content":"简单测试"}]}
4.2 性能优化建议
在切换为processed模式后,需要注意:
- 延迟增加:LLM生成通常比直接检索慢300-800ms
- 成本变化:每个请求会增加LLM token消耗
- 结果缓存:对相同问题实现缓存可提升性能
推荐监控指标:
- 端到端响应时间P99
- LLM调用错误率
- 平均token消耗/请求
5. 生产环境经验总结
在实际部署中,我们总结出以下黄金法则:
混合模式策略:
- 简单事实性问题:使用raw模式快速返回精确匹配
- 复杂分析性问题:启用processed模式生成答案
异常处理规范:
def handle_response(response): if response.type == "raw_json": if is_simple_fact(response): return format_as_answer(response) else: return fallback_to_llm(response) else: return response文档预处理技巧:
- 在索引阶段添加
instruction字段指导LLM - 对技术文档添加"步骤"、"注意"等标记
- 限制片段长度在300-500字符之间
- 在索引阶段添加
这个问题的解决不仅关乎技术配置,更需要理解RAG架构的数据流向。正确的处理方式应该像经验丰富的顾问——先收集资料(raw),再加工成客户需要的建议(processed),而不是直接扔出原始材料。