【Azure 架构师学习笔记 】- Azure AI(23) -AI知识库Agent平台(3)-RAG 智能检索问答

本文属于【Azure 架构师学习笔记】系列

本文属于【Azure AI】系列

接上文 【Azure 架构师学习笔记 】- Azure AI(23) -AI知识库Agent平台(2)-文档向量化与向量库存储

前言

本文为 RAG(Retrieval-Augmented Generation,检索增强生成)智能检索问答系统的完整实现教程。

一、功能完整说明

RAG 系统是 AI 知识库的核心功能,解决了传统大模型"记忆有限、易编造内容"的痛点,核心逻辑是"先检索、再生成",本次实现的功能如下:

  • 用户交互:支持命令行输入问题,输入"quit"即可退出;
  • 语义检索:基于用户问题生成向量,与 Milvus 向量库中存储的文档片段进行相似度匹配,筛选出最相关的内容(默认取前3条,可灵活调整);
  • 精准回答:调用 GPT-4 模型,严格基于检索到的知识库内容生成回答,不编造、不偏离文档原意;
  • 日志监控:沿用前两天的日志工具,记录用户问题、检索过程、回答结果,方便排查问题、追溯操作;
  • 兼容性:完全复用原有代码。

简单来说,前两天我们完成了"把文档存入知识库"的操作(写入),第三天则完成"从知识库中找答案"的操作(读取+生成端),两者结合,就构成了一个完整的企业级AI知识库。

二、核心原理

RAG 系统的核心优势的是"检索增强",避免大模型"一本正经地胡说八道",其完整工作流程分为4步:

  1. 用户输入问题:比如"test.txt 文档里包含哪些内容?",系统接收用户输入的自然语言问题;
  2. 问题向量生成:调用 text-embedding-3-large 模型,将用户问题转换成 3072 维的向量;
  3. 语义检索:Milvus 向量库根据问题向量,计算库中所有文档片段向量的相似度,筛选出相似度最高的前N条(本次默认3条),作为回答的"参考资料";
  4. 智能生成回答:将检索到的参考资料和用户问题,一起传入 GPT-4 模型,模型基于参考资料生成精准、贴合原意的回答,同时避免编造内容。

代码实现

在根目录创建文件 rag_chat.py:

python 复制代码
from utils.logger import logger
from llm.azure_llm import AZURE_LLM_CLIENT  # 复用第二天的Azure LLM客户端
from storage.milvus_client import MILVUS_CLIENT  # 复用第二天的Milvus客户端

class RAGChatBot:
    def __init__(self):
        """
        初始化RAG问答机器人
        复用前序代码中的全局客户端,避免重复初始化,提升效率
        """
        self.llm = AZURE_LLM_CLIENT  # 加载Azure OpenAI客户端(已配置GPT-4和Embedding模型)
        self.milvus = MILVUS_CLIENT  # 加载Milvus向量库客户端(已连接集合)
        self.collection_name = "enterprise_knowledge_base"  # 与前两天的向量库集合名一致
        self.top_k = 3  # 检索时取前3条最相关的文档片段(可调整,越多越全面但速度稍慢)
        logger.info(" RAG 问答机器人初始化完成,可开始输入问题进行问答")

    def search_related_content(self, question: str):
        """
        核心检索函数:根据用户问题,从Milvus向量库中检索最相关的文档片段
        :param question: 用户输入的自然语言问题
        :return: 拼接后的相关文档片段(字符串),作为GPT回答的参考资料
        """
        # 1. 生成问题的向量(与文档向量维度一致:3072维)
        query_vector = self.llm.get_embedding(question)
        logger.info(f" 已生成问题向量,维度:{len(query_vector)}(与配置一致)")

        # 2. 调用Milvus的search方法,进行语义相似度检索
        # 重点:output_fields指定返回的字段,与前两天存入的字段(text、doc_name)一致
        search_results = self.milvus.client.search(
            collection_name=self.collection_name,  # 目标向量库集合
            data=[query_vector],  # 待检索的问题向量(列表格式,支持批量检索)
            limit=self.top_k,  # 检索前top_k条最相关的内容
            output_fields=["text", "doc_name"],  # 检索后返回的字段:文本内容、文档名称
            metric_type="IP"  # 相似度计算方式:内积(适合向量相似度对比,无需修改)
        )

        # 3. 提取检索结果,拼接成可直接用于GPT提示词的格式
        related_context = []
        for idx, result in enumerate(search_results[0], 1):
            # 提取单条检索结果的信息
            doc_name = result["entity"]["doc_name"]  # 文档名称(如test.txt)
            text = result["entity"]["text"]  # 文档片段内容
            similarity = result["distance"]  # 相似度(值越接近1,相关性越高)
            # 拼接成结构化的文本,方便GPT识别
            related_context.append(f"【相关文档{idx}】文档名称:{doc_name},相似度:{round(similarity, 3)},内容:{text}")

        # 若未检索到相关内容,返回提示信息
        if not related_context:
            logger.warning(" 未从知识库中检索到相关内容")
            return "未从知识库中检索到与问题相关的内容,无法回答,请尝试更换问题表述。"
        
        # 拼接所有相关内容,返回给GPT
        context_str = "\n\n".join(related_context)
        logger.info(f" 检索完成,共找到{len(related_context)}条相关内容")
        return context_str

    def ask(self, question: str):
        """
        问答主函数:接收用户问题,完成检索+回答生成
        :param question: 用户输入的自然语言问题
        :return: GPT生成的精准回答(字符串)
        """
        # 记录用户问题(日志监控)
        logger.info(f" 用户问题:{question}")

        # 步骤1:检索相关内容(调用上面的检索函数)
        context = self.search_related_content(question)

        # 步骤2:构造GPT提示词(关键:引导GPT只基于检索到的内容回答,不编造)
        prompt = f"""
你是一个专业的企业AI知识库助手,你的核心职责是基于用户提供的参考资料,精准回答用户问题,严格遵循以下规则:
1.  回答必须完全基于提供的参考资料,不得编造任何未提及的内容,若资料中没有相关信息,直接说明"未检索到相关内容";
2.  回答要简洁明了、逻辑清晰,贴合用户问题,不要添加无关内容;
3.  若参考资料中有多条相关内容,需整合所有信息,避免重复;
4.  若用户问题与参考资料无关,直接拒绝回答,不要勉强编造。

参考资料:
{context}

用户问题:{question}

请按照上述规则,生成回答:
        """

        # 步骤3:调用GPT-4生成回答(复用前两天的chat_completion方法,无需重新配置)
        answer = self.llm.chat_completion(prompt)
        logger.info(f" 生成回答完成,长度:{len(answer)}字符")

        return answer

# 主函数:运行RAG问答系统(命令行交互)
if __name__ == "__main__":
    # 初始化RAG机器人
    rag_bot = RAGChatBot()

    # 命令行交互界面(简洁易懂,适合测试)
    print("=" * 60)
    print(" 企业级AI知识库 RAG 问答系统(第三天最终版)")
    print(" 说明:输入问题即可获取知识库中的精准回答,输入 'quit' 退出系统")
    print("=" * 60 + "\n")

    # 循环接收用户输入,实现连续问答
    while True:
        try:
            user_input = input("请输入你的问题:")
            # 退出逻辑
            if user_input.lower().strip() == "quit":
                print("\n感谢使用,系统已退出!")
                logger.info(" RAG 问答系统已正常退出")
                break
            # 空输入处理
            if not user_input.strip():
                print("请输入有效的问题,不要输入空内容!")
                continue
            # 生成回答并打印
            response = rag_bot.ask(user_input)
            print(f"\n 回答:{response}")
            print("-" * 60 + "\n")
        except Exception as e:
            # 异常处理,避免系统崩溃,同时记录日志
            error_msg = f"问答过程中出现异常:{str(e)}"
            print(f" {error_msg},请稍后重试!")
            logger.error(error_msg)

详细运行说明

运行前请确认:前两天的代码已正常跑通(文档已存入Milvus向量库)、config.yaml配置正确(向量维度3072、Azure密钥有效),然后按照以下步骤操作,与第二天的运行方式完全一致:

  1. 准备工作(确认环境)
  • 确认 Docker 中的 Milvus 容器已启动(若未启动,运行命令:docker start milvus-standalone);
  • 确认前两天的依赖包已安装(无需新增依赖,沿用之前的环境即可);
  • 确认 test.txt 文档已成功存入 Milvus 向量库(可运行第二天的 check_milvus.py 查看数据)。
  1. 运行命令
    打开终端,进入项目根目录(与 document_processor.py、check_milvus.py 同级),运行以下命令:
python 复制代码
python rag_chat.py
  1. 运行效果示例


  1. 关键注意点(避免运行报错)
  • 若提示"Azure 连接失败":检查 config.yaml 中的 endpoint、api_key 是否正确,网络是否正常;
  • 若提示"Milvus 连接失败":检查 Docker 中的 Milvus 容器是否启动,port 配置是否为 19530;
  • 若回答"未检索到相关内容":检查 test.txt 是否已成功存入向量库,或问题表述是否与文档内容相关;
  • 若想调整检索条数:修改代码中 self.top_k = 3,数值越大,检索内容越全面,但生成回答速度稍慢。

常见问题排查

结合前两天的运行经验,整理第三天最可能出现的3个问题,给出具体排查方法,适合学习时参考,也可作为文章的"问题排查"章节:

问题1:运行后提示"未检索到相关内容"

排查步骤:

  1. 运行 check_milvus.py,确认 Milvus 向量库中是否有数据;
  2. 若没有数据:重新运行第二天的 document_processor.py,确保文档成功存入;
  3. 若有数据:检查用户问题与文档内容是否相关(比如文档是"AI知识库搭建",问题是"天气如何",则无法检索到内容);
  4. 若问题相关仍无法检索:调整 self.top_k 数值(比如改为5),或检查 Embedding 模型是否正确(确保是 text-embedding-3-large)。
    问题2:GPT 回答编造内容
    排查步骤:
  5. 检查 prompt 提示词,确保包含"必须基于参考资料回答,不得编造"的约束;
  6. 确认检索到的 context 内容是否正确(可在代码中添加 print(context) 打印检索结果);
  7. 检查 GPT 部署名是否正确(config.yaml 中的 deployment_name_gpt4 需与 Azure 中的部署名一致)。
    问题3:运行时出现"维度不匹配"报错
    排查步骤:
  8. 确认 config.yaml 中 vector_dim: 3072(与 text-embedding-3-large 维度一致);
  9. 确认 Milvus 集合已重建为 3072 维度(可重新运行 reset.py 删除旧表,重新生成新表);
  10. 确认 get_embedding方法返回的向量维度是 3072(可添加 print(len(query_vector)) 验证)。

总结

今天我们完成了 RAG 智能检索问答系统的完整实现,核心是"复用前序代码、实现检索+生成闭环",与前两天的内容形成完整的 AI 知识库搭建流程:

  1. 第一天:搭建基础环境(Azure OpenAI、Milvus),配置 config.yaml,定义核心客户端;
  2. 第二天:实现文档处理(读取、分块、生成向量),将文档存入 Milvus 向量库,可查看库中数据;
  3. 第三天:实现 RAG 问答(问题向量生成、语义检索、GPT 回答),完成"存入-检索-回答"的完整闭环。
相关推荐
进击monkey2 小时前
降本增效 + 安全合规:PandaWiki 知识库,企业数字化转型的权限管理优选
人工智能·机器人·开源·ai知识库
Dev7z2 小时前
基于深度学习的口腔疾病自主诊断系统设计与实现(UI界面+训练代码+数据集)
人工智能·深度学习·口腔疾病
IT大师兄吖2 小时前
whisperx 语音转字幕 懒人整合包
人工智能
前端不太难2 小时前
AI 驱动游戏:鸿蒙生态的机会在哪里?
人工智能·游戏·harmonyos
鹧鸪云光伏2 小时前
AI赋能储能设计系统,让设计更简单
人工智能·信息可视化·数据分析·光伏·储能设计方案
fof9202 小时前
Base LLM | 从 NLP 到 LLM 的算法全栈教程 第五天
人工智能·自然语言处理
乘凉~2 小时前
【MoneyPrinterTurbo】一个利用AI大模型一键生成高清短视频的工具,开源免费,只要有电脑就能用
人工智能·电脑·音视频
Thomas.Sir2 小时前
第四章:RAG知识库开发之【深入浅出 Naive RAG:从零构建你的第一个检索增强生成系统】
ai·chatgpt·检索增强·知识库·naive rag
久违 °2 小时前
【AI-Agent】OpenClaw 对接飞书应用机器人
ai·机器人·飞书