Skip to content

以下是对 gc-qa-rag-server/ragapp/services/research.py 文件的详细 Markdown 文档说明:


文档:research.py 代码详解

文件概述

本文件实现了一个面向“研究型”问答的异步服务流程,核心功能包括:将用户提出的复杂问题自动拆解为若干子问题,针对每个子问题进行知识库检索与答案生成,并最终对所有子问题的答案进行综合总结。该流程充分利用了大语言模型(LLM)的强大理解与生成能力,并结合了异步编程和并行处理,极大提升了多轮复杂问答的效率和智能化水平。

主要组件与函数说明

1. OpenAI 客户端与模型配置

文件开头通过 AsyncOpenAI 实例化了一个异步 OpenAI 客户端,所有的 LLM 调用均通过该客户端进行。模型的 API Key、Base URL、模型名称等参数均从统一的配置文件 app_config 中读取,便于灵活切换和统一管理。

2. chat 异步生成器

该函数封装了与 OpenAI 聊天模型的异步交互。它接受一组消息(messages),调用 OpenAI 的流式接口(stream=True),并以异步生成器的方式逐步产出模型生成的文本片段。这种流式输出方式可以显著提升用户体验,实现“边生成边显示”的效果,尤其适合长文本或多轮对话场景。

3. split_questions 子问题拆解

该函数的核心任务是:根据用户原始问题和知识库检索结果,自动生成一组子问题。其实现思路如下:

  • 首先将知识库检索结果(hits)序列化为 JSON 文本,便于后续拼接到提示词中。
  • 构造一个详细的提示词(prompt),明确要求模型将用户问题拆解为若干子问题,并以 JSON 数组的形式输出。
  • 将该提示词插入到消息列表的最后一条用户消息中,确保模型能够结合上下文和检索结果进行推理。
  • 最终调用 chat 函数,返回一个异步生成器,产出模型的流式输出。

这种“提示词工程”结合上下文和检索结果的设计,极大提升了子问题拆解的相关性和准确性。

4. research_hits 研究型问答主流程

这是本文件的核心异步函数,实现了完整的“研究型”问答流程。其主要步骤如下:

  • 首先调用 split_questions,获取针对原始问题的子问题列表。该过程通过 get_llm_full_result 封装,确保能够获取完整的模型输出。
  • 对每个子问题,定义了一个异步处理函数 process_sub_question,其内部会针对子问题进行知识库检索(search_sementic_hybrid),并调用 LLM 生成答案(summary_hits)。
  • 通过 asyncio.gather 并行处理所有子问题,极大提升了整体处理效率。
  • 将所有子问题及其答案插入到消息历史中,便于后续综合总结时参考上下文。
  • 最后,调用 summary_hits_think,对所有子问题的答案进行综合总结,生成最终的研究型答案。

该流程充分体现了“分而治之”的思想:先将复杂问题拆解为若干可控的子问题,分别检索和回答,再进行全局总结。这种设计不仅提升了答案的全面性和深度,也便于后续的可解释性分析。

5. extract_json_content 辅助函数

该函数用于从文本中提取被 ```json 代码块包裹的内容。其实现方式为正则表达式匹配,若找到则返回代码块内的内容,否则返回原始文本。该函数在处理 LLM 输出时非常实用,因为模型常常以代码块形式输出结构化数据。


实现原理与设计考虑

1. 异步与并行处理

整个流程采用了 Python 的异步编程(async/await)和并行任务调度(asyncio.gather),极大提升了多子问题处理的效率。尤其在面对多个子问题时,可以同时发起检索和生成请求,显著缩短整体响应时间。

2. 提示词工程与上下文融合

在子问题拆解和答案生成过程中,均充分利用了上下文信息(如用户原始问题、知识库检索结果、历史消息等),并通过精心设计的提示词引导模型输出结构化、可用的结果。这种“上下文融合+提示词工程”的设计,是提升 LLM 应用效果的关键。

3. 结构化输出与健壮性

无论是子问题列表还是最终答案,均要求模型以结构化格式(如 JSON)输出,并通过辅助函数进行解析。这种设计便于后续自动化处理和接口对接。同时,对于模型输出的异常情况(如格式不符),也有相应的容错处理,保证了系统的健壮性。

4. 日志与调试

文件中大量使用了 logger 进行调试和信息记录,便于开发和运维过程中追踪问题、分析流程。这体现了良好的工程实践。


应用场景

该模块适用于需要对复杂问题进行自动化研究、分解和综合回答的场景,如智能问答、学术研究助手、企业知识库问答等。通过自动拆解、并行检索和综合总结,可以显著提升系统的智能化水平和用户体验。


代码示例

# 假设有如下输入
keyword = "请分析人工智能在医疗领域的主要应用及挑战"
messages = [{"role": "user", "content": keyword}]
hits = [...]  # 知识库检索结果
product = "医疗"

# 异步调用主流程
result = await research_hits(client, keyword, messages, hits, product)
print(result)
# 输出为对所有子问题答案的综合总结

总结

research.py 通过异步编程、提示词工程、结构化输出和上下文融合,实现了复杂问题的自动拆解、并行检索与综合回答。其设计兼顾了效率、智能性和健壮性,是智能问答和知识研究系统中的核心服务模块。