open webui源码分析9-知识库
本文介绍了OpenWebUI知识库组件的创建和使用方法。知识库用于存储结构化信息,使系统响应更个性化。
知识库是open webui的一个重要组件,您可以在其中存储系统在交互过程中可以参考的结构化信息,从而使响应更加个性化,有更强的场景感知能力。以下几种情况下考虑使用知识库:
- 经常需要引用的重要项目信息或特定数据
- 需要使用的自定义命令、工作流或配置
- 每次聊天中都需要遵循相同的偏好、指南或规则
- 在多个成员之间共享知识
本文先创建一个简单的知识库,再分析知识库的创建过程代码,然后说明如何使用知识库,接下来对于直接应用知识库代码进行分析,再接下来对于创建自带知识库大模型源码进行分析,最后对于在对话中使用自带知识库大模型的代码进行分析。
一、创建知识库
创建知识库本身非常简单,进入【工作空间】并选择【知识库】,进入知识库页面。

点击[+]进入增加知识库页面,然后填写主题、目标并设置可见性:

点击【创建知识】,完成知识库创建,进入知识库列表页面

用户点击【+】,可添加知识:

我们上传一个文件,完成知识库的知识添加:

二、数据模型
知识库相关表包括knowledge和file表,knowledge存储知识库基本信息,file表存储知识库的文件,二者为1:n的关系,file结构在系列1已讲解,在此不再赘述,knowledge结构如下:

其中:
id:知识库唯一标识
user_id:创建知识库的用户唯一标识
name:知识库名称,创建时用户输入
description:知识库描述,创建时用户输入
data:知识库引用的文件
meta:知识库元数据
created_at:知识库创建时间
updated_at:知识库更新时间
access_control:知识库访问权限
三、创建过程分析
知识库创建过程主要包括三个步骤,先创建库并保存基本信息,然后是上传知识库文件,最后是把知识库与文件关联。
1)创建知识库
创建知识库请求数据如下:
{
"name": "北京市2024年政府工作报告",
"description": "为各部门编写明年工作计划提供参考",
"access_control": null
}
对应入口函数为create_new_knowledge,该方法很简单,调用Knowledges.insert_new_knowledge把知识库记录插入到knowledge表中,并返回知识库信息到前端,具体如下:
@router.post("/create", response_model=Optional[KnowledgeResponse])
async def create_new_knowledge(
request: Request, form_data: KnowledgeForm, user=Depends(get_verified_user)
):
if user.role != "admin" and not has_permission(
user.id, "workspace.knowledge", request.app.state.config.USER_PERMISSIONS
):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=ERROR_MESSAGES.UNAUTHORIZED,
)knowledge = Knowledges.insert_new_knowledge(user.id, form_data)
if knowledge:
return knowledge
else:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.FILE_EXISTS,
)
insert_new_knowledge方法的代码也是简单易懂,直接贴在这里,不做分析:
def insert_new_knowledge(
self, user_id: str, form_data: KnowledgeForm
) -> Optional[KnowledgeModel]:
with get_db() as db:
knowledge = KnowledgeModel(
**{
**form_data.model_dump(),
"id": str(uuid.uuid4()),
"user_id": user_id,
"created_at": int(time.time()),
"updated_at": int(time.time()),
}
)try:
result = Knowledge(**knowledge.model_dump())
db.add(result)
db.commit()
db.refresh(result)
if result:
return KnowledgeModel.model_validate(result)
else:
return None
except Exception:
return None
返回到前端数据如下:
{
"id": "4c8c248b-0f31-4193-a571-225aa28398a5",
"user_id": "e6d4a214-8982-40ad-9bbc-77ee14534d58",
"name": "北京市2024年政府工作报告",
"description": "为各部门编写明年工作计划提供参考",
"data": null,
"meta": null,
"access_control": null,
"created_at": 1756195064,
"updated_at": 1756195064,
"files": null
}
2)上传文件
上传文件具体分析见系列1
3)关联文件
关联文件请求数据如下:
{"file_id":"56d30a2a-2566-44b6-8105-362b1834fd88"} #刚刚上传文件唯一标识
关联文件入口函数为add_file_to_knowledge_by_id,具体代码如下。
@router.post("/{id}/file/add", response_model=Optional[KnowledgeFilesResponse])
def add_file_to_knowledge_by_id(
request: Request,
id: str, #路径参数,知识库唯一标识
form_data: KnowledgeFileIdForm,
user=Depends(get_verified_user),
):#根据知识库唯一标识从knowledge查询
knowledge = Knowledges.get_knowledge_by_id(id=id)if not knowledge:#不存在则报400错误
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.NOT_FOUND,
)if ( #权限检查,如果没有权限则报400错误
knowledge.user_id != user.id
and not has_access(user.id, "write", knowledge.access_control)
and user.role != "admin"
):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
)#根据文件唯一标识查file表
file = Files.get_file_by_id(form_data.file_id)
if not file:#如果文件不存在,则返回400错误
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.NOT_FOUND,
)
if not file.data:#如果文件内容为空,则返回400错误
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.FILE_NOT_PROCESSED,
)# 把内容插入到向量库
try:
process_file(
request,#collection_name=id保证一个知识库所有文件插入到一个集合中
ProcessFileForm(file_id=form_data.file_id, collection_name=id),
user=user,
)
except Exception as e:
log.debug(e)
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e),
)#下面的检查没意义,因为前面的代码已经检查,如果knowledge为空,则返回错误
if knowledge:
data = knowledge.data or {}
file_ids = data.get("file_ids", []) #从knowledge的data字段获取file_idsif form_data.file_id not in file_ids: #保证表单中携带的file_id在file_ids中
file_ids.append(form_data.file_id) # 把文件fild_id增加到file_ids中#更新knowledge的data字段
data["file_ids"] = file_idsknowledge = Knowledges.update_knowledge_data_by_id(id=id, data=data)
if knowledge:
files = Files.get_file_metadatas_by_ids(file_ids)return KnowledgeFilesResponse(#返回知识库完整信息
**knowledge.model_dump(),
files=files,
)
else:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.DEFAULT("knowledge"),
)
else:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.DEFAULT("file_id"),
)
else:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.NOT_FOUND,
)
完成文件与知识库关联后返回前端数据如下:
{
"id": "4c8c248b-0f31-4193-a571-225aa28398a5",
"user_id": "e6d4a214-8982-40ad-9bbc-77ee14534d58",
"name": "北京市2024年政府工作报告",
"description": "为各部门编写明年工作计划提供参考",
"data": {
"file_ids": [
"56d30a2a-2566-44b6-8105-362b1834fd88",……
]
},
"meta": null,
"access_control": null,
"created_at": 1756195064,
"updated_at": 1756195256,
"files": [
{
"id": "56d30a2a-2566-44b6-8105-362b1834fd88",
"meta": {
"name": "beijing_annual_report_2024.pdf",
"content_type": "application/pdf",
"size": 329811,
"data": {},
"collection_name": "4c8c248b-0f31-4193-a571-225aa28398a5"
},
"created_at": 1756195250,
"updated_at": 1756195250
}
]
}
四、使用知识库
使用知识库有两种方式,一种是在对话时直接引用,一种是对基础大模型挂接创建好的知识库,相当于创建自带知识库的大模型。
1)直接引用
直接引用知识库非常简单,在聊天窗口输出‘#’便弹出知识库及文件列表,用户可以选择知识库获直接选择知识库中的文件,具体见下图:

2)基础大模型挂接知识库
进入【工作空间】并选择【模型】进入模型管理页面:

用户点击【+】进入新增模型页面,在该页面可以填写模型名称、选择基础模型、填写描述和设置可见性,还可以调整模型参数:

用户点击【选择】知识,显示可挂接知识库列表

用户可以选择一个知识库完成挂载。当然,用户也可以通过【上传文件】直接为模型挂载外部知识。
挂载了知识库的大模型成为一个新的模型,用户可以在对话式跟选择其他大模型一样自由选择。
五、直接引用知识库分析
1)获取知识库列表
用户输入‘#’后,前端会调用后端接口获取知识库列表。对应入口为:
http://{ip:port}/api/v1/knowledge/
该方法逻辑很简单。就是访问knowledge表并返回知识库列表,所以不予分析
@router.get("/", response_model=list[KnowledgeUserResponse])
async def get_knowledge(user=Depends(get_verified_user)):……
应答消息如下:
[
{#以下是知识库基本信息
"id": "4c8c248b-0f31-4193-a571-225aa28398a5",
"user_id": "e6d4a214-8982-40ad-9bbc-77ee14534d58",
"name": "北京市2024年政府工作报告",
"description": "为各部门编写明年工作计划提供参考",
"data": {
"file_ids": [
"56d30a2a-2566-44b6-8105-362b1834fd88"
]
},
"meta": null,
"access_control": null,
"created_at": 1756195064,
"updated_at": 1756195256,#以下是知识库归属用户信息
"user": {
"id": "e6d4a214-8982-40ad-9bbc-77ee14534d58",
"name": "acaluis",
"email": "acaluis@sina.com",
"role": "admin",
"profile_image_url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAAXNSR0IArs4c6QAABItJREFUeF7tnF2IVHUYxp9zzpyZ2Q9ZtdZscfdmEzOtZfEDtmhtIxXRQEQIuxFUikRFKOou0RtRgrqIBNmCQLab6IM1yjVaK8QLBVGkUlwFFSoldHXdna+dE3OOLnvOfszsTLXPP565G+Z/Zp7z/M5z3vO+/2Wte52zPehF44AlIDQsfCECwsVDQMh4CIiAsDlApkc1REDIHCCTo4QICJkDZHKUEAEhc4BMjhIiIGQOkMlRQgSEzAEyOUqIgJA5QCZHCREQMgfI5CghAkLmAJkcJURAyBwgk6OECAiZA2RylBABIXOATI4SIiBkDpDJUUIEhMwBMjlGJyS58ghiTWtGLPWy95E5vRfZXz8ms7l0OcYCceYsRbKjE1ZtY+hsc9d7kOrZVLoDZCuNBRJf9i7ii7cDthuy1Bu6hdRPOzB843syq0uTYyyQqrVH4cxt88/SG7oJK14HOAnAyyN78VOkT75VmgNkq4wEEmveiETbAViJmb6duWvfwXm0BVb14/77/O3fMNS9Gl52gMzu4nKMBJJ47j24CzYDlg0Mp5E59z6cuc/CaWgPEmNwcTcOiF3XjOTKLth1TwTmD/6O1I9vwKlfgnjr28Ftq5AaQ4u7cUDcp7YhvmwPrFi1b/zwH6cw9M06RJ+6TC3uxgFJrvoMscZVwc04n0XmwkfInN7nvw31JYYWd6OAOA3PI7ni0Ejx9gauI9W7DcM3z/hA3IVbg/S4NQGv/stIHX8V+f6+4tWUZIVRQKK9R7ROROuLX/DPHkTm3AckdheXYRSQ6vW9sB95JijmucFgTPJLZ+gsQ09gBhZ3Y4BEe4+JbkfRdaYVd2OAJF84jFjzhsJ/AynkA9lLXUj/vGvce0DVum/hPLY8+Myw4m4EkDG9R/oO0qfeQa7v83GBRGuNScXdCCDxlt2hpi//13kMftUxYYUcMwk2qLgbAWSy3mMiKqFjRjWQxZ9zpncFPRBn3ktItn8Iq6q+Iqe89G2kT76J3NWvK/qef/tgeiCJ5fvgLnodsGOVeWFIcacGYrm1qFrbPdJ7VEbEjM6dGog7fxPibfthuTOCJ9jBP/1Ru5fpL4mNXdMA9+mdI/smJnTu1EDCvUd5I/XR3X2B4sPpcElEp2ERLRC7vhXJFz+BXdsU2FLmo2u0J/GK9DDTwCD0k7RAxvQeA9eQ+mEL8rfOTsmz6IS40OXn+r5A6sRrU/qe/2oxLZDRf8RQMCN35Ut/1F7OK9qT5O9eRarnFcqxPCWQaO9R6R55dJex3NtfORfDVI+hBBIdoVc6ixqzT0Jc3OmA+L3Hy8dgz3rywcU1+WS31CswCpm1uNMBiW7D/lPGRfdJWIs7HZBSr/j/6zoBISMrIAJC5gCZHCVEQMgcIJOjhAgImQNkcpQQASFzgEyOEiIgZA6QyVFCBITMATI5SoiAkDlAJkcJERAyB8jkKCECQuYAmRwlREDIHCCTo4QICJkDZHKUEAEhc4BMjhIiIGQOkMlRQgSEzAEyOUqIgJA5QCZHCREQMgfI5CghAkLmAJkcJURAyBwgk6OEkAH5G7gElAPcU3ncAAAAAElFTkSuQmCC"
},#以下是知识库文件信息
"files": [
{
"id": "56d30a2a-2566-44b6-8105-362b1834fd88",
"meta": {
"name": "beijing_annual_report_2024.pdf",
"content_type": "application/pdf",
"size": 329811,
"data": {},
"collection_name": "4c8c248b-0f31-4193-a571-225aa28398a5"
},
"created_at": 1756195250,
"updated_at": 1756195250
}
]
}
]
2)发起补足请求
发起补足请求时,数据如下:
{
"stream": true,
"model": "qwen3:1.7b",
"messages": [
{
"role": "user",
"content": "请简单总结一下北京是2023年政府工作报告内容"
},
{
"role": "assistant",
"content": "\n2023年北京政府工作报告指出,全年地区生产总值增长5.2%(约4.4万亿元),一般公共预算收入增长8.2%(突破6000亿元),城镇调查失业率4.4%。报告强调全面贯彻落实党的二十大精神,统筹推进京津冀协同发展、国际交往中心建设、法治政府建设等重点工作,提出要深化“五子”联动、提升城市功能,推动高质量发展。同时,注重稳中求进、改革创新,强化风险防范,确保经济和社会稳定。 [1]"
},
{
"role": "user",
"content": "有哪些保护历史文化名城的举措?"
}
],
"params": {},
"files": [
{
"id": "56d30a2a-2566-44b6-8105-362b1834fd88",
"meta": {
"name": "beijing_annual_report_2024.pdf",
"content_type": "application/pdf",
"size": 329811,
"data": {},
"collection_name": "4c8c248b-0f31-4193-a571-225aa28398a5"
},
"created_at": 1756195250,
"updated_at": 1756195250,
"collection": {
"name": "北京市2024年政府工作报告",
"description": "为各部门编写明年工作计划提供参考"
},
"name": "beijing_annual_report_2024.pdf",
"description": "北京市2024年政府工作报告 - 为各部门编写明年工作计划提供参考",
"knowledge": true,
"type": "file",
"status": "processed"
}
],
"tool_servers": [],
"features": {
"image_generation": false,
"code_interpreter": false,
"web_search": false,
"memory": false
},
"variables": {
"{{USER_NAME}}": "acaluis",
"{{USER_LOCATION}}": "Unknown",
"{{CURRENT_DATETIME}}": "2025-08-26 21:53:22",
"{{CURRENT_DATE}}": "2025-08-26",
"{{CURRENT_TIME}}": "21:53:22",
"{{CURRENT_WEEKDAY}}": "Tuesday",
"{{CURRENT_TIMEZONE}}": "Etc/GMT-8",
"{{USER_LANGUAGE}}": "zh-CN"
},
"model_item": {
"id": "qwen3:1.7b",
"name": "qwen3:1.7b",
"object": "model",
"created": 1756216316,
"owned_by": "ollama",
"ollama": {
"name": "qwen3:1.7b",
"model": "qwen3:1.7b",
"modified_at": "2025-08-20T03:50:50.085066919Z",
"size": 1359293444,
"digest": "8f68893c685c3ddff2aa3fffce2aa60a30bb2da65ca488b61fff134a4d1730e7",
"details": {
"parent_model": "",
"format": "gguf",
"family": "qwen3",
"families": [
"qwen3"
],
"parameter_size": "2.0B",
"quantization_level": "Q4_K_M"
},
"connection_type": "local",
"urls": [
0
],
"expires_at": 1756216600
},
"connection_type": "local",
"tags": [],
"actions": [],
"filters": []
},
"session_id": "BOfZ2Yucswcg5PgRAAAJ",
"chat_id": "1a56ce9b-f31c-4fe2-8ffa-a6f5e9ff2f69",
"id": "134db67e-11c3-48f1-a072-2130a31c7e6c",
"background_tasks": {
"follow_up_generation": true
}
}
此时处理逻辑完全与系列4-初级RAG相同,可参见open webui源码分析4-初级RAG-CSDN博客,此处不再赘述。
六、创建自带知识库的大模型
1)数据模型
自带知识库大模型涉及的表为model表,model表结构如下:

id:大模型唯一标识
user_id:大模型创建者唯一标识
base_model_id:基础大模型唯一标识
name:大模型名称
meta:大模型元数据
params:大模型参数
created_at:大模型创建时间
updated_at:大模型信息修改时间
access_control:权限
is_active:是否激活
2)创建过程分析
创建自带知识库大模型请求参数如下:
{
"id": "openwebui", #自带知识库大模型唯一标识
"base_model_id": "deepseek-r1:1.5b", #基础模型
"name": "政府工作报告", #大模型名称
"meta": {
"profile_image_url": "/static/favicon.png",
"description": "挂接2023年北京市政府工作报告",
"suggestion_prompts": null,
"tags": [],
"capabilities": { #大模型的各项能力
"vision": false, #视觉
"file_upload": false,#wenjian shangchuan
"web_search": false, #web搜索
"image_generation": false, #生成图片
"code_interpreter": false, #代码解释
"citations": false #支持应用
},
"knowledge": [#知识库信息
{
"id": "161dd6ea-2e14-4b60-b8a2-48993ec9e4f2",
"user_id": "e6d4a214-8982-40ad-9bbc-77ee14534d58",
"name": "政府工作报告",
"description": "共享政府工作报告内容",
"data": {
"file_ids": [
"ca856fca-3eef-44d7-882d-24b312a72c48"
]
},
"meta": null,
"access_control": null,
"created_at": 1756275107,
"updated_at": 1756275184,
"user": {
"id": "e6d4a214-8982-40ad-9bbc-77ee14534d58",
"name": "acaluis",
"email": "acaluis@sina.com",
"role": "admin",
"profile_image_url": "data:image/png;base64,CC"
},
"files": [
{
"id": "ca856fca-3eef-44d7-882d-24b312a72c48",
"meta": {
"name": "microsoft_annual_report_2022.pdf",
"content_type": "application/pdf",
"size": 1285495,
"data": {},
"collection_name": "161dd6ea-2e14-4b60-b8a2-48993ec9e4f2"
},
"created_at": 1756275120,
"updated_at": 1756275120
}
],
"type": "collection" #这里的type设置很重要,后面会用到
}
]
},
"params": {},
"access_control": null
}
创建自带知识库大模型入口为http://{ip:port}/api/v1/models/create,对应方法为create_new_model,该方法非常简单。
@router.post("/create", response_model=Optional[ModelModel])
async def create_new_model(
request: Request,
form_data: ModelForm,
user=Depends(get_verified_user),
):# 权限检查,保证不会非法创建
if user.role != "admin" and not has_permission(
user.id, "workspace.models", request.app.state.config.USER_PERMISSIONS
):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=ERROR_MESSAGES.UNAUTHORIZED,
)model = Models.get_model_by_id(form_data.id)
if model:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=ERROR_MESSAGES.MODEL_ID_TAKEN,
)else:
model = Models.insert_new_model(form_data, user.id)#大模型插入到model表中
if model:
return model
else:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=ERROR_MESSAGES.DEFAULT(),
)
七、访问自带知识库大模型分析
补足请求报文如下:
{
"stream": true,
"model": "open-webui",
"messages": [
{
"role": "user",
"content": "如何给大模型挂载知识库"
}
],
"params": {},
"tool_servers": [],
"features": {
"image_generation": false,
"code_interpreter": false,
"web_search": false,
"memory": false
},
"variables": {
"{{USER_NAME}}": "acaluis",
"{{USER_LOCATION}}": "Unknown",
"{{CURRENT_DATETIME}}": "2025-08-27 09:52:59",
"{{CURRENT_DATE}}": "2025-08-27",
"{{CURRENT_TIME}}": "09:52:59",
"{{CURRENT_WEEKDAY}}": "Wednesday",
"{{CURRENT_TIMEZONE}}": "Etc/GMT-8",
"{{USER_LANGUAGE}}": "zh-CN"
},
"model_item": {
"id": "open-webui",
"name": "open webui",
"object": "model",
"created": 1756258460,
"owned_by": "ollama",
"info": {
"id": "open-webui",
"user_id": "e6d4a214-8982-40ad-9bbc-77ee14534d58",
"base_model_id": "qwen3:1.7b",
"name": "open webui",
"params": {},
"meta": {
"profile_image_url": "/static/favicon.png",
"description": "open webui相关知识",
"capabilities": {
"vision": true,
"file_upload": true,
"web_search": true,
"image_generation": true,
"code_interpreter": true,
"citations": true
},
"suggestion_prompts": null,
"tags": [],
"knowledge": [
{
"id": "31e80ee3-fac1-4641-85f8-b18befdeccf7",
"user_id": "e6d4a214-8982-40ad-9bbc-77ee14534d58",
"name": "open webui",
"description": "提供openwebui所有技术文档",
"data": {
"file_ids": [
"fb73f36c-8d7a-47c3-97e7-773f86e0e671",
"...",
"60d87f8b-ba0c-48af-861f-d9a648e947ac"
]
},
"meta": null,
"access_control": null,
"created_at": 1756257946,
"updated_at": 1756258216,
"user": {
"id": "e6d4a214-8982-40ad-9bbc-77ee14534d58",
"name": "acaluis",
"email": "acaluis@sina.com",
"role": "admin",
"profile_image_url": "data:image/png;base64,iVBO……CC"
},
"files": [#所有文件向量化到一个集合中,并且集合名与知识库id相同
{
"id": "60d87f8b-ba0c-48af-861f-d9a648e947ac",
"meta": {
"name": "yacy.md",
"content_type": "application/octet-stream",
"size": 1342,
"data": {},
"collection_name": "31e80ee3-fac1-4641-85f8-b18befdeccf7"
},
"created_at": 1756258215,
"updated_at": 1756258215
},
"..."
]
}
]
},
"access_control": null,
"is_active": true,
"updated_at": 1756258460,
"created_at": 1756258460
},
"preset": true,
"actions": [],
"filters": [],
"tags": []
},
"session_id": "UcI0SMW8hwAaKZPyAAAF",
"chat_id": "d6aef4da-3cba-439c-aaad-341844bf4bca",
"id": "08f6a2a1-da85-490a-9f83-728fcee1a104",
"background_tasks": {
"title_generation": true,
"tags_generation": true,
"follow_up_generation": true
}
}
与自带知识库大模型对话时,知识库相关部分处理集中在process_chat_payload方法中,具体如下。
相关大模型自带知识库处理流程如下:
1)从模型中获取其自带知识库信息
2)开始向量库查询前发送通知到前端
3)把知识库数据追加到表单的 files中
4)调用chat_completion_files_handler执行RAG相关处理
5)把向量库查询完成状态通知前端
async def process_chat_payload(request, form_data, user, metadata, model):
……
#直接获取大模型自带知识库信息
model_knowledge = model.get("info", {}).get("meta", {}).get("knowledge", False)
if model_knowledge:
await event_emitter(#通过websocket把当前状态(搜索知识库)发送到前端
{
"type": "status",
"data": {
"action": "knowledge_search",
"query": user_message,
"done": False,
},
}
)knowledge_files = []
for item in model_knowledge:#遍历自带知识库,追加到 knowledge_files数组中
if item.get("collection_name"):#如果知识库是集合
knowledge_files.append(
{
"id": item.get("collection_name"),
"name": item.get("name"),
"legacy": True,
}
)
elif item.get("collection_names"):#如果知识库是多个集合
knowledge_files.append(
{
"name": item.get("name"),
"type": "collection",
"collection_names": item.get("collection_names"),
"legacy": True,
}
)
else: #刚刚创建挂接知识库大模型走这个分支
knowledge_files.append(item)files = form_data.get("files", [])
files.extend(knowledge_files) #把知识库数据追加到表单files中
form_data["files"] = files #更新表单files内容……
try:#调用chat_completion_files_handler执行RAG相关处理
form_data, flags = await chat_completion_files_handler(request, form_data, user)
sources.extend(flags.get("sources", []))
except Exception as e:
log.exception(e)……
if model_knowledge: #最后发送知识库查询完成消息通过websocket推送到前端
await event_emitter(
{
"type": "status",
"data": {
"action": "knowledge_search",
"query": user_message,
"done": True,
"hidden": True,
},
}
)
与大模型自带知识库相关的代码在chat_completion_files_handler中,该方法在RAG中已经做分析,此处不再重复贴代码。现在需要对其中的get_sources_from_items方法进行重点分析。针对当前的带知识库大模型,item.type='collection',所以重点分析该分支的代码。
本方法根据传入的数据找到所有的collection,然后调用向量库查询。
有一点需要注意******:大模型自带知识库情况下,知识库所有文件均存储在向量库的同一个集合中,这个集合的唯一标识与知识库唯一标识相同******。
def get_sources_from_items(
request,
items,
queries,
embedding_function,
k,
reranking_function,
k_reranker,
r,
hybrid_bm25_weight,
hybrid_search,
full_context=False,
user: Optional[UserModel] = None,
):
log.debug(
f"items: {items} {queries} {embedding_function} {reranking_function} {full_context}"
)extracted_collections = []
query_results = []for item in items:
query_result = None
collection_names = []if item.get("type") == "text":
……
elif item.get("type") == "note":
……
elif item.get("type") == "file":
……elif item.get("type") == "collection":#重点代码在这里
if (
item.get("context") == "full"
or request.app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL
):#该分支不需要考虑
……
else:
if item.get("legacy"):#该分支不需要考虑
collection_names = item.get("collection_names", [])
else:#把知识库id,同时也是向量库集合id,追加到collection_names列表中
collection_names.append(item["id"])elif item.get("docs"):
……
elif item.get("collection_name"):
……
elif item.get("collection_names"):
……if query_result is None and collection_names: #查询向量库多个集合
collection_names = set(collection_names).difference(extracted_collections)
if not collection_names:
log.debug(f"skipping {item} as it has already been extracted")
continuetry:
if full_context: #缺省不走本分支
query_result = get_all_items_from_collections(collection_names)
else:
query_result = None # Initialize to None
if hybrid_search:#缺省不走本分支
try:
query_result = query_collection_with_hybrid_search(
collection_names=collection_names,
queries=queries,
embedding_function=embedding_function,
k=k,
reranking_function=reranking_function,
k_reranker=k_reranker,
r=r,
hybrid_bm25_weight=hybrid_bm25_weight,
)
except Exception as e:
log.debug(
"Error when using hybrid search, using non hybrid search as fallback."
)#重点在这里。查询知识库所有文件所在的向量库集合
if not hybrid_search and query_result is None:
query_result = query_collection(
collection_names=collection_names,
queries=queries,
embedding_function=embedding_function,
k=k,
)
except Exception as e:
log.exception(e)extracted_collections.extend(collection_names)
if query_result:
if "data" in item: #如果知识库中有data项,则删除
del item["data"]#删除了data的知识库到query_result并追加到query_results列表中
query_results.append({**query_result, "file": item})sources = []
for query_result in query_results:#根据所有查询组织返回数据
try:
if "documents" in query_result:
if "metadatas" in query_result:
source = {#用查询结果设置source,document,metadata和distance
"source": query_result["file"],
"document": query_result["documents"][0],
"metadata": query_result["metadatas"][0],
}
if "distances" in query_result and query_result["distances"]:
source["distances"] = query_result["distances"][0]sources.append(source)
except Exception as e:
log.exception(e)return sources
更多推荐

所有评论(0)