Skip to content

AI 框架封装 ​

概述 ​

模块路径:backend/app/api/v1/module_ai/framework 定位:AI 大模型应用的底层能力层,对 LangChain、LangGraph、LlamaIndex、OpenAI/兼容协议、联网搜索、异步任务等做统一抽象,供「模型管理 / 知识库 / 智能对话 / 智能写作」等上层业务直接复用。


设计目标 ​

为了让上层业务从具体的 AI 基础设施实现中解耦,框架层做了三件事:

  • 统一抽象:用一套工厂 + 单例封装 LlamaIndex 各原生组件(Embedding、VectorStore、Retriever、NodeParser、Postprocessor),上层只关心「要做什么」,不关心「背后是哪个引擎」。
  • 多后端可插拔:向量库支持 Chroma / Milvus / Qdrant / PGVector,Embedding 支持 Ollama / Xinference / OpenAI 兼容,重排支持 Xinference / SiliconFlow,联网搜索支持 Bing / 智谱——切换后端只改配置或一行参数。
  • 生产可用性:内置客户端/实例缓存、配置变更重建、模型可达性预检、异常兜底(联网搜索失败不阻断对话)、异步任务队列(文档解析异步化)。

约定:RAG能力基于 LlamaIndex 封装,不重复造轮子。


整体结构 ​

framework/
├── settings.py            # 框架配置(向量库/联网搜索)
├── llm/                   # 大模型对话封装(OpenAI 兼容协议)
│   ├── base.py            # ChatMessage / ChatRequest / ChatStreamChunk / ChatClient
│   └── factory.py         # AiModelFactory 单例
├── embedding/             # 向量化(Embedding)封装
│   └── factory.py         # LlamaEmbeddingFactory 单例
├── vector/                # 向量存储封装
│   └── factory.py         # LlamaVectorStoreFactory 单例
├── loader/                # 文档加载(多格式解析)
│   ├── core.py            # load / read_url / download_bytes
│   └── reader.py          # HtmlContentReader
├── splitter/              # 文本切分封装
│   └── factory.py         # SplitterFactory 单例
├── retriever/             # 检索器 + 检索管道
│   ├── factory.py         # get_retriever 工厂方法
│   └── pipeline.py        # RetrievalPipeline 两阶段召回
├── postprocessor/         # 节点后处理 / 重排
│   ├── factory.py         # get_postprocessor 工厂方法
│   └── rerank.py          # resolve_rerank_postprocessor
├── websearch/             # 联网搜索
│   ├── base.py            # WebSearchBase 抽象基类
│   ├── factory.py         # WebSearchFactory 单例
│   ├── provider_bing.py   # BingSearch
│   └── provider_zhipu.py  # ZhipuSearch
└── task_queue/            # 异步任务 Worker(arq)
    └── worker.py          # WorkerSettings

组件说明 ​

大模型对话 llm/ ​

基于 AsyncOpenAI 对 OpenAI 兼容协议做封装,兼容任意 OpenAI 协议的大模型(OpenAI、DeepSeek、Ollama、Xinference、智谱等)。

  • base.py 定义请求/响应数据类与 ChatClient:
    • ChatMessage:对话消息,content 支持 str(纯文本)或 list[dict](多模态 content parts,如图片 URL)。
    • ChatRequest:统一请求(messages / model / temperature / max_tokens / stream / extra 等),extra 透传厂商特有参数(如推理参数)。
    • ChatClient:提供 chat_completion(一次性返回)与 chat_completion_stream(流式,ChatStreamChunk 把正文 content 与推理过程 reasoning_content 分离产出)。
  • factory.py 的 AiModelFactory 是单例:按 平台:模型 缓存并复用 AsyncOpenAI 客户端,密钥或 base_url 变更时自动重建;resolve_key 解析密钥(优先 api_key 表)与 base_url(模型自定义 > 密钥自定义)。

前端对应:对话交互在 apps/web-ele/src/views/ai/chat/,流式对话由 chat/index/composables/use-chat-stream.ts 驱动;消息渲染拆分为 message/parts/ 下的 text-part(正文)、reasoning-part(推理过程)、knowledge-part(知识库引用)、web-search-part(联网搜索),与后端 ChatStreamChunk 的字段一一对应。

向量模型 embedding/ ​

LlamaEmbeddingFactory 单例,按 provider 返回 LlamaIndex 原生 BaseEmbedding:

provider实现说明
openai / openaicompatOpenAIEmbedding兼容 OpenAI 协议(含 SiliconFlow、DeepSeek 等)
ollamaOllamaEmbedding本地部署
xinferenceXinferenceEmbeddingXinference 自托管

工厂按 provider:model 缓存实例,构造后做轻量预检(Ollama 校验 GET /api/tags 模型是否已下载;OpenAI 兼容校验 GET /v1/models),不可达或模型缺失时抛面向用户的 CustomException。

前端对应:向量化模型的「平台 / 模型名 / 服务地址 / 密钥」在 apps/web-ele/src/views/ai/model/ 下的 apiKey(密钥)与 model(模型,含 EMBEDDING 类型)页面配置,配置即决定 get_embedding 的入参。

向量存储 vector/ ​

LlamaVectorStoreFactory 单例,支持四种后端,按 backend:collection 缓存:

backend实现必需配置
chromaChromaVectorStore本地持久化目录(默认 ./static/chroma_data)
milvusMilvusVectorStore连接地址 + 向量维度(dim)
qdrantQdrantVectorStore连接地址 + API Key
pgvectorPGVectorStorePostgreSQL 连接信息 + 向量维度

显式入参 > 框架配置(ModuleAiSettings)> 内置默认值。额外提供 update_node_metadata 用于合并更新已入库节点元数据(当前支持 Chroma / Milvus)。

前端对应:向量后端类型与连接信息由后端环境变量配置(见「配置」);知识库对应的集合/向量维度在 apps/web-ele/src/views/ai/knowledge/knowledge/manage/(知识库管理表单)中设置,入库时驱动 get_store 与 update_node_metadata。

文档加载 loader/ ​

core.py 的 load(content, filename) 把文件字节解析为 LlamaIndex Document:

  • 通过 SimpleDirectoryReader + FILE_EXTRACTOR 分发多格式 Reader(PDF / DOCX / PPTX / XLSX / CSV / RTF / HTML 等)。
  • _sniff_real_ext 按二进制魔数嗅探真实格式(如 docx 被改名为 md),避免二进制当纯文本解码乱码。
  • HtmlContentReader(自定义)用 BeautifulSoup 清洗网页,移除 script/style 等噪声。
  • read_url / download_bytes 支持从 URL 下载并解析;is_image_url 用于识别多模态图片附件。

前端对应:文档上传与解析在 apps/web-ele/src/views/ai/knowledge/document/,上传步骤 document/form/modules/upload-step.vue 把文件交给后端 loader 解析入库;解析状态由 task_queue(见下)异步推进并在文档列表页实时展示。

文本切分 splitter/ ​

SplitterFactory 单例,按策略返回 LlamaIndex 原生 NodeParser,按 strategy:chunk_size:chunk_overlap:kwargs 缓存:

  • AUTO:按扩展名自动选择(md→Markdown、html→HTML、json→JSON、代码→Code、其它→Sentence)。
  • SENTENCE / TOKEN / MARKDOWN / CODE / HTML / JSON / SEMANTIC(语义切分需 embed_model)/ SENTENCE_WINDOW / PARENT_CHILD(父子分块)。

前端对应:分段设置在 apps/web-ele/src/views/ai/knowledge/document/form/modules/split-step.vue,可选「分块策略 / 分块大小 / 重叠大小」,其 splitStrategy 取值与后端 SplitStrategyEnum 完全对齐(默认 auto),并可调用后端接口实时预览分段效果。

检索器与检索管道 retriever/ ​

  • factory.py 的 get_retriever 工厂方法,按 RetrieverName 枚举装配 LlamaIndex 原生检索器:向量检索、BM25 关键词、查询融合(混合)、自动合并、递归、路由、向量自动检索。BM25 针对中英混合做了 token 规则与停用词优化。

  • pipeline.py 的 RetrievalPipeline 编排两阶段召回:

    • 检索器粗召回(按 RECALL_MULTIPLIER=5 放大候选量,可按 recallK 覆盖);
    • Rerank 重排(可选)→ 相似度阈值过滤 → 截断 top_k。

    管道只负责编排顺序,Embedding / VectorStore / Rerank 实例由调用方解析后传入;knowledge_id 用于向量库元数据过滤,避免跨知识库串库。

前端对应:召回效果验证在 apps/web-ele/src/views/ai/knowledge/knowledge/retrieval/index.vue(文档召回测试),可输入查询文本并设置 topK 与「相似度阈值」,实时查看各分段 score 与内容,对应 RetrievalPipeline 的入参与输出。

后处理与重排 postprocessor/ ​

  • factory.py 的 get_postprocessor 工厂方法,按 PostprocessorName 装配 LlamaIndex 原生后处理器(相似度过滤、关键词过滤、LLM 重排、SentenceTransformer 重排、长上下文重排、时间加权等)。
  • rerank.py 的 resolve_rerank_postprocessor 面向「重排模型」配置:按平台返回 XinferenceRerank(私有化)或 SiliconFlowRerank(云端),要求配置服务地址与密钥。

前端对应:重排模型作为 model 的一种类型(RERANK)在 apps/web-ele/src/views/ai/model/model/ 配置,知识库启用重排后即驱动 resolve_rerank_postprocessor 接入检索管道。

联网搜索 websearch/ ​

基于抽象基类 WebSearchBase,统一返回 AiWebSearchPageSchema(title / url / snippet):

  • WebSearchFactory 单例按配置 WEB_SEARCH_PROVIDER 构建客户端。
  • BingSearch:解析 Bing 搜索结果页,免密钥(锁定中文市场、忽略系统代理防国际版)。
  • ZhipuSearch:调用智谱 Web Search API,返回结构化结果(含来源/发布时间),需 API Key。
  • search 方法带异常兜底:失败时返回空列表,不阻断主对话链路。

前端对应:搜索提供方由后端环境变量配置;对话中命中的联网结果由 apps/web-ele/src/views/ai/chat/index/message/parts/web-search-part.vue 以可展开列表 + 详情抽屉渲染(标题 / 摘要 / 来源 / 原文链接),与 AiWebSearchPageSchema 字段对应。

异步任务队列 task_queue/ ​

基于 arq(Redis 后端)的异步 Worker,用于文档解析等耗时任务异步化、可水平扩展:

bash
uv run arq app.api.v1.module_ai.framework.task_queue.worker.WorkerSettings

WorkerSettings 复用 task_queue_settings(队列名、Redis、并发、超时、重试),队列名须与投递端一致。

前端对应:文档入库后的解析、向量化等耗时步骤投递到该队列异步执行;前端 apps/web-ele/src/views/ai/knowledge/document/ 通过轮询/状态展示解析进度,避免阻塞用户操作。