开源知识库项目WeKnora技术拆解

背景

WeKnora 是腾讯(Tencent)开发的一套企业级知识库管理系统,主要用于构建和管理基于大语言模型(LLM)的知识增强应用。从代码结构和功能实现来看,这是一个功能完备的知识管理服务平台,具有以下核心特点:

核心功能
  1. 多源知识导入

    • 支持从文件上传(PDF、TXT、DOCX、Markdown等文档格式)
    • 支持从URL导入网页内容
    • 支持直接输入文本段落
    • 支持图片等多模态内容处理
  2. 智能文档处理

    • 文档自动分块(chunking)处理
    • 内容摘要自动生成
    • 多语言支持
    • 高级分块策略配置(分块大小、重叠、分隔符等)
  3. 多模态处理能力

    • 图片内容识别(OCR)
    • 图像描述生成(通过VLM视觉语言模型)
    • 支持多种图片格式(JPG、PNG、GIF等)
    • 多模态内容与文本内容的关联处理
  4. 知识图谱构建

    • 支持GraphRAG(知识图谱增强检索)
    • 实体和关系自动提取
    • 构建知识间的语义关联
    • 支持实体、关系等知识图谱元素的存储和检索
  5. 向量检索系统

    • 集成多种向量数据库引擎
    • 支持批量索引和查询
    • 基于嵌入模型的语义搜索
    • 支持多租户的向量存储隔离
技术架构特点
  1. 微服务架构

    • 模块化设计,如docreader服务专门处理文档解析
    • 服务间通过gRPC通信(proto定义)
    • 清晰的接口抽象和依赖管理
  2. 多租户支持

    • 租户存储配额管理
    • 租户级别的知识隔离
    • 租户配置定制化(如检索引擎配置)
  3. 企业级特性

    • 完整的错误处理和日志追踪
    • OpenTelemetry支持的分布式追踪
    • 请求级别的上下文管理
    • 配额管理和资源控制
  4. 可扩展性设计

    • 支持多种嵌入模型配置
    • 可插拔的检索引擎架构
    • 可配置的分块和处理策略
    • 支持自定义摘要生成提示词

模块架构关系图

image

基础框架

  • Web框架:Gin
  • 消息队列:Asynq

数据库系统

  • PostgreSQL 12+,带有用于向量操作的pgvector扩展
  • MySQL 8.0+(替代主数据库)
  • Elasticsearch 7.x或8.x用于向量搜索(可选)

AI和ML服务

  • 用于本地LLM(大型语言模型)托管的Ollama
  • 用于文档文本提取的PaddlePaddle与PaddleOCR
  • 用于AI模型执行的Python 3.8+运行时

容器平台

  • 用于容器化部署的Docker 20.10+和Docker Compose
  • 支持GPU的容器运行时(用于GPU加速)

存储和缓存

  • 用于流媒体和会话管理的Redis 6.0+
  • MinIO(可选,用于S3兼容的对象存储)

链路跟踪

  • Jaeger(Jaeger)是 Uber 开发的开源分布式追踪系统,用于监控和诊断微服务架构中的请求链路。
  • OpenTelemetry

前端

  • Vue.js,Typescript, TDesign,Pinia, Vite

聊天功能数据流

image

多模态文档处理

image

文档向量化处理流程

WeKnora 的文档向量化处理采用完整的异步机制,主要流程包括文档解析、分块处理、向量生成和索引存储四个阶段 。

异步处理机制

系统在创建知识条目时立即采用异步处理模式 knowledge.go:203-206 。无论是文件上传、URL内容还是文本段落,都会启动独立的 goroutine 进行后台处理 knowledge.go:330-332 。

image
核心处理流程
1. 文档解析阶段

文档首先通过 docReaderClient.ReadFromFile 进行解析和分块 knowledge.go:583-596 。解析过程支持多模态处理,包括 OCR 文字提取和图像描述生成。

2. 分块处理阶段

系统将解析后的内容传递给 processChunks 方法进行向量化处理 knowledge.go:608-610 。该方法负责创建文本块、图像块和实体关系块等不同类型的数据块。

image
3. 向量生成阶段

通过嵌入模型为每个文本块生成向量表示 knowledge.go:694-700 。系统支持批量向量生成以提高效率 keywords_vector_hybrid_indexer.go:74-85 。

image
4. 索引存储阶段

生成的向量通过复合检索引擎存储到多个后端系统 composite.go:190-208 。支持 PostgreSQL (pgvector) 和 Elasticsearch 等向量数据库。

image
并发优化机制

文档解析服务采用多层并发优化:

  • 文档级并发:大文档按页面并行处理 docx_parser.py:696-730
image
  • 图像处理并发:使用信号量控制图像处理的并发度 base_parser.py:1248-1267
image
  • 向量化批处理:将内容分批进行向量生成,避免内存溢出 keywords_vector_hybrid_indexer.go:86-97
Notes

整个向量化流程通过 gRPC 协议在不同服务间协调 docreader.proto:8-13 ,确保了系统的模块化和可扩展性。处理状态会实时更新到数据库,用户可以通过 API 查询处理进度。

image

文档处理模块采用Python语言编写主要基于以下几个技术原因:

Python在文档处理领域的生态优势

文档处理模块需要处理多种格式的文档,包括PDF、Word、图片等,Python在这个领域有丰富的成熟库支持 init.py:4-10 。从代码中可以看到,该模块集成了多个专业的Python库:

  • OCR处理:使用PaddleOCR进行图像文字识别 download_deps.py:7
  • Word文档处理:使用python-docx库处理DOCX格式 docx_parser.py:9
image
  • PDF处理:使用pypdf库进行PDF文本提取 pdf_parser.py:6
  • 图像处理:使用PIL进行图像操作 docx_parser.py:8
多模态AI处理能力

文档处理模块需要支持多模态内容处理,包括文本提取、图像识别和OCR功能 README.md:70 。Python在AI/ML领域的生态系统非常成熟,特别是在深度学习框架和预训练模型的支持方面 Dockerfile.docreader:36-46 。

并发处理和性能优化

尽管Python在性能上有一定限制,但文档处理模块通过多进程并行处理来解决这个问题 docx_parser.py:839-851 。代码显示使用了ProcessPoolExecutor实现真正的多核并行化处理 docx_parser.py:1262-1287 。

微服务架构的适配性

文档处理模块作为独立的微服务运行,通过gRPC接口提供服务 docreader_pb2_grpc.py:8-11 。Python的gRPC支持和容器化部署能力使其很适合这种架构模式 server.py:15-17 。

Notes

文档处理模块是WeKnora系统中的一个独立服务,专门负责各种文档格式的解析和内容提取。选择Python主要是因为其在文档处理、OCR、图像处理等领域有丰富的第三方库支持,能够快速集成各种AI模型和处理工具。虽然Python在执行速度上不如编译型语言,但通过多进程并行处理和合理的架构设计,能够满足文档处理的性能需求。

消息队列的使用场景

1. 异步任务处理

WeKnora使用了Asynq作为异步任务队列系统 config.go:21 。这主要用于处理文档解析、向量化等耗时操作,避免阻塞用户请求。

2. 流式响应管理

系统实现了基于Redis的流式管理器来处理实时消息传输 config.go:24 。在知识问答场景中,系统会注册流式响应通道来处理LLM的实时输出 session.go:760-764 。

3. 服务器端事件流(SSE)

WeKnora采用Server-Sent Events机制来实现实时的问答交互 API.md:1203 。当用户提问时,系统会通过SSE推送知识检索结果和LLM生成的回答 session.go:767-777 。

架构中的消息流转

在RAG流水线中,消息队列主要支持以下场景:

  • 文档处理流水线:文档上传后通过异步队列进行OCR、文本提取、向量化等处理
  • 实时问答交互:用户查询通过流式管道实现增量式回答生成
  • 多轮对话管理:会话状态和消息历史通过Redis缓存和流式管理器维护
Notes

WeKnora的消息队列设计主要围绕异步处理和实时交互两个核心需求。系统使用Asynq处理后台任务,Redis Stream管理实时消息流,SSE提供前端实时更新能力。这种设计确保了文档处理的高效性和用户交互的流畅性。

架构选择的核心考虑

  1. 轻量级部署需求

    WeKnora设计为可以快速部署的文档理解框架,使用Docker Compose即可一键启动 docker-compose.yml:152-162 。引入Kafka会增加系统复杂度和资源消耗,不符合轻量化部署的目标。

  2. 实时性优先的场景特点

    系统主要处理两类消息流:

异步任务队列:使用Asynq基于Redis实现 asyncq.go:14-26 ,支持文档处理等后台任务的优先级队列 asyncq.go:54-58 。

实时流式响应:采用Redis Stream + SSE机制 redis_manager.go:25-30 ,直接支持LLM流式输出的实时传输 session.go:224-247 。

  1. 简化的消息模式
    WeKnora的消息场景相对简单:

文档处理任务的异步执行

问答会话的流式响应传输

会话状态的临时存储

这些场景不需要Kafka的复杂特性如分区、副本、持久化等。

  1. 统一的存储后端
    系统统一使用Redis作为缓存、队列和流式管理的后端 factory.go:17-35 ,减少了基础设施的复杂性,便于运维管理。

技术实现对比

相比Kafka方案,当前架构的优势:

部署简单:只需Redis一个中间件

延迟更低:直接基于Redis的内存操作

资源占用小:适合中小规模部署

开发复杂度低:API更简洁直观

MinIO的业务场景

MinIO在WeKnora系统中主要用于文件存储后端,作为本地文件系统存储的替代方案 .env.example:21-22 。系统支持三种存储类型:本地存储(local)、MinIO对象存储(minio)和腾讯云COS(cos) container.go:201-237 。

具体功能实现

MinIO服务通过minioFileService结构体实现,提供以下核心功能 minio.go:16-20 :

  1. 文件上传:将用户上传的文档保存到MinIO存储桶中 minio.go:53-78
  2. 文件下载:从MinIO获取存储的文档文件 minio.go:80-101
  3. 文件删除:删除不再需要的文档文件 minio.go:103-126
部署配置

当配置文件中STORAGE_TYPE=minio时,系统会自动启动MinIO服务 start_all.sh:241-252 。需要配置以下环境变量 .env.example:80-91 :

  • MINIO_ENDPOINT:MinIO服务器地址
  • MINIO_ACCESS_KEY_ID:访问密钥
  • MINIO_SECRET_ACCESS_KEY:密钥
  • MINIO_BUCKET_NAME:存储桶名称
在RAG系统中的作用

在WeKnora的RAG(检索增强生成)架构中,MinIO负责存储用户上传的原始文档文件,这些文件经过处理后会被分块、向量化并存储到向量数据库中用于检索 knowledge.go:405-408 。

Jaeger模块的业务场景和部署必要性

Jaeger模块在WeKnora中主要用于分布式链路追踪,帮助监控和调试微服务架构中的请求流转过程。

业务场景

Jaeger在WeKnora中的主要业务场景包括:

  1. 请求链路追踪:跟踪用户请求在各个微服务间的完整调用链路,包括文档处理、向量检索、LLM推理等服务 init.go:41-52
  2. 性能监控:监控各个服务的响应时间和性能瓶颈,特别是在RAG流水线中的文档解析、向量化处理、检索和生成等关键环节
  3. 故障排查:当系统出现问题时,通过链路追踪快速定位故障发生的具体服务和环节
是否可以省去部署

可以省去部署,但会失去重要的监控能力。

从配置来看,Jaeger的启用是可选的:

  • docker-compose.yml中,Jaeger作为独立服务运行在端口16686 docker-compose.yml:107-126
  • 应用通过环境变量OTEL_EXPORTER_OTLP_ENDPOINT连接到Jaeger服务 docker-compose.yml:23-28
  • 如果没有设置OTLP端点,系统会降级到标准输出模式 init.go:53-59

省去部署的影响:

  • ✅ 系统核心功能(文档理解、检索、问答)不受影响
  • ❌ 失去分布式追踪能力,难以监控性能和排查问题
  • ❌ 在生产环境中缺乏重要的可观测性工具

启动脚本显示Jaeger作为标准服务之一提供Web界面访问 start_all.sh:543-547 。

Notes

Jaeger是WeKnora架构中的可观测性组件,主要用于开发和运维阶段的监控调试。对于简单的测试或演示环境可以省去,但在生产环境中建议保留以确保系统的可维护性。

通过环境变量配置模型

.env 文件中,您可以配置不同类型的模型: .env.example:124-172

LLM 模型配置:

  • INIT_LLM_MODEL_NAME - 模型名称
  • INIT_LLM_MODEL_BASE_URL - 模型访问地址(可选)
  • INIT_LLM_MODEL_API_KEY - API 密钥(可选)

Embedding 模型配置:

  • INIT_EMBEDDING_MODEL_NAME - 嵌入模型名称
  • INIT_EMBEDDING_MODEL_DIMENSION - 向量维度
  • INIT_EMBEDDING_MODEL_ID - 模型标识符

Rerank 模型配置:

  • INIT_RERANK_MODEL_NAME - 重排模型名称
  • INIT_RERANK_MODEL_BASE_URL - 访问地址
  • INIT_RERANK_MODEL_API_KEY - API 密钥
通过 API 接口创建模型

使用 REST API 创建自定义模型: API.md:664-676

支持的模型类型包括:

  • LLM - 大语言模型
  • EMBEDDING - 嵌入模型
  • RERANK - 重排模型

模型来源支持:

  • OPENAI - OpenAI API
  • LOCAL - 本地模型(如 Ollama)
  • REMOTE - 其他远程 API
通过 Go SDK 创建模型

使用 Go 客户端 SDK 创建模型: example.go:84-101

SDK 支持的模型类型常量: model.go:66-77

系统内部模型管理

系统内部通过 ModelService 接口管理模型: model.go:13-30

模型数据结构定义: model.go:48-74

系统启动时会自动初始化配置的模型: test_data.go:388-443

Notes

WeKnora 的模型配置系统非常灵活,支持本地模型(通过 Ollama)和远程 API 模型。您可以根据需要选择最适合的配置方式。对于生产环境,建议使用 API 接口或 SDK 进行动态模型管理,而环境变量配置更适合初始化默认模型。

代码走查

我们抽取一个业务逻辑serivice代码,knowledge.go这个文件1744行,让Qwen3帮我们走查下

github.com/Tencent/WeK...

代码质量一般:

Code Review: 知识库服务代码分析

硬编码(Hard Code)问题

1. 文件类型硬编码

代码中存在多处文件类型硬编码,这限制了系统的可扩展性:

go 复制代码
// 在isValidFileType函数中  
switch strings.ToLower(getFileType(filename)) {  
case "pdf", "txt", "docx", "doc", "md", "markdown", "png", "jpg", "jpeg", "gif":  
     return true  
default:  
     return false  
}

// 在IsImageType函数中  
switch fileType {  
case "jpg", "jpeg", "png", "gif", "webp", "bmp", "svg", "tiff":  
     return true  
default:  
     return false  
}  

问题:

  • 文件类型列表直接写死在代码中,无法通过配置动态扩展
  • 当需要支持新文件类型时,必须修改代码并重新部署

建议:

  • 将支持的文件类型列表移到配置文件中
  • 通过服务初始化时加载配置

2. 存储提供商硬编码

存储提供商的处理逻辑也是硬编码的:

go 复制代码
switch kb.StorageConfig.Provider {  
case "cos":  
     // COS配置检查  
case "minio":  
     // MinIO配置检查  
}  

问题:

  • 仅支持"cos"和"minio"两种存储提供商
  • 添加新的存储提供商需要修改核心业务逻辑

建议:

  • 实现存储提供商接口,通过工厂模式动态创建
  • 配置中指定存储提供商类型,而不是在代码中硬编码判断

3. 魔法数字问题

代码中存在多处"魔法数字",缺乏可读性:

go 复制代码
// 在processChunks函数中  
chunk.ChunkIndex = maxSeq + i*100 + 1  // 100, 1是魔法数字  
chunk.ChunkIndex = maxSeq + i*100 + 2  // 100, 2是魔法数字  
sChunk.ChunkIndex = maxSeq + 3         // 3是魔法数字

// 其他地方  
if chunk.EndAt > 4096 {  
     break  
}  

问题:

  • 数字常量没有解释其含义
  • 修改时容易出错,难以理解设计意图

建议:

  • 定义有意义的常量替代魔法数字
  • 例如: const ChunkIndexOffset = 100const MaxContentLength = 4096

4. 环境变量直接检查

环境变量检查直接嵌入业务逻辑:

go 复制代码
enableGraphRAG := os.Getenv("ENABLE_GRAPH_RAG") == "true"  

问题:

  • 与配置系统耦合,不利于测试
  • 环境变量检查分散在代码各处

建议:

  • 在配置服务中统一处理环境变量
  • 通过配置对象提供功能开关

其他代码质量问题

1. 函数过长且职责不单一

processChunks函数超过200行,承担了过多职责:

  • 处理文本和图片chunk
  • 生成摘要
  • 创建索引
  • 更新知识状态
  • 调整租户存储使用

建议 : 拆分为多个单一职责的函数,如processTextChunks, processImageChunks, generateSummary

2. 重复代码

DeleteKnowledgeDeleteKnowledgeList函数中有大量重复逻辑,特别是在错误处理和资源清理方面。

建议 : 提取公共逻辑到辅助函数,如deleteKnowledgeResources

3. 错误处理不一致

有些错误被记录但没有返回,有些则直接返回:

go 复制代码
if err := s.repo.UpdateKnowledge(ctx, knowledge); err != nil {  
     span.RecordError(err)  
     return  
}

// vs

if err != nil {  
     logger.GetLogger(ctx).WithField("error", err).Errorf("...")  
     span.RecordError(err)  
     return  
}  

建议: 统一错误处理策略,确保所有错误都被适当记录和处理

4. 代码风格不一致

  • 有些注释是中文,有些是英文
  • 错误日志记录方式不统一(logger.ErrorWithFields vs logger.GetLogger(ctx).WithField...Errorf

建议: 统一日志记录方式和注释语言

5. 可测试性问题

  • 直接使用全局配置和外部服务
  • 缺乏接口抽象,难以进行单元测试

建议:

  • 使用接口替代具体实现
  • 通过依赖注入提供可测试的mock对象

6. 潜在性能问题

  • 大文件处理时使用io.ReadAll(f)可能导致内存问题
  • 大量数据库操作未考虑批处理优化

建议:

  • 对大文件使用流式处理
  • 优化数据库批量操作

改进建议总结

  1. 消除硬编码 :

    • 将文件类型、存储提供商等配置移到配置文件中

    • 用有意义的常量替代魔法数字

  2. 重构代码结构 :

    • 拆分长函数为单一职责的小函数

    • 提取重复代码到公共函数

    • 统一错误处理策略

  3. 提高可测试性 :

    • 使用接口抽象外部依赖

    • 通过依赖注入提供可测试性

  4. 优化性能 :

    • 改进大文件处理方式

    • 优化数据库批量操作

  5. 统一代码风格 :

    • 统一日志记录方式

    • 统一注释语言

这些改进将使代码更加灵活、可维护、可测试,同时减少未来扩展时的代码修改量。特别是消除硬编码问题,将使系统更容易适应未来的需求变化,无需修改核心业务逻辑即可支持新的文件类型或存储提供商。

安全

WeKnora 支持使用 AES 加密对租户数据进行加密。这点对信创不太好,需要改造支持国密算法。

image

配置安全管理

系统通过环境变量和配置文件管理敏感信息 config.go:14-25 ,包括数据库连接、租户配置等关键参数,避免硬编码敏感信息。

image

API密钥

WeKnora使用AES-GCM加密算法生成安全的API密钥 tenant.go:217-247 。密钥生成过程包括:

租户ID加密:将租户ID转换为字节数组,使用AES-GCM加密 tenant.go:219-239

随机nonce生成:每次生成12字节的随机nonce确保密钥唯一性 tenant.go:229-232

Base64编码:将nonce和密文组合后进行Base64编码 tenant.go:242-246

生成的API密钥格式为sk-{encrypted_part},其中encrypted_part包含了加密的租户ID信息。

image

请求拦截与验证流程

跳过无需认证的API:系统定义了无需认证的API列表,如创建租户接口 auth.go:17-30

提取API密钥:从HTTP请求头X-API-Key中获取API密钥 auth.go:47-53

解析租户ID:调用ExtractTenantIDFromAPIKey解析密钥中的租户ID auth.go:55-63

数据库验证:查询数据库验证API密钥的有效性 auth.go:65-82

image

前端集成

前端通过Axios拦截器自动添加API密钥到请求头 request.ts:77-80 ,支持从本地存储或测试数据中获取密钥 request.ts:54-59 。

认证机制缺陷

缺乏速率限制

认证中间件没有实现速率限制 auth.go:33-95 ,容易受到暴力破解攻击。攻击者可以无限制地尝试不同的API密钥。

无会话管理

系统采用无状态的API密钥认证,缺乏会话管理和令牌撤销机制。一旦API密钥被盗用,无法立即阻止未授权访问。

权限控制粗粒度

认证中间件只验证API密钥的有效性 auth.go:76-82 ,缺乏细粒度的权限控制。所有通过认证的请求都具有相同的访问权限。

数据隔离缺陷

上下文依赖风险

租户隔离严重依赖上下文中的租户ID chunk.go:110-111 。如果上下文被污染或篡改,可能导致跨租户数据访问。

image
缺乏数据访问审计

系统没有实现完整的数据访问审计机制,难以追踪和检测潜在的数据泄露或未授权访问。

输入验证缺陷

预处理不够全面

查询预处理插件虽然清理了一些常见的输入 preprocess.go:24-29 ,但缺乏对SQL注入、XSS等攻击的防护。

image

我们看看仅仅用正则匹配

缺乏输入长度限制

系统没有对输入数据的长度进行严格限制,可能导致DoS攻击或缓冲区溢出。

配置安全缺陷

敏感信息暴露

Docker配置文件中直接暴露了多个敏感的环境变量 docker-compose.yml:48-59 ,包括数据库密码、API密钥等,存在配置泄露风险。

缺乏配置加密

所有配置信息都以明文形式存储,没有实现配置文件加密或安全的密钥管理。

前端安全缺陷

客户端密钥存储

前端代码将API密钥存储在本地 request.ts:55-59 ,容易被恶意脚本或浏览器扩展获取。

缺乏CSRF保护

HTTP请求配置中没有实现CSRF令牌保护,可能受到跨站请求伪造攻击。

多租户设计

数据库层面的租户隔离

WeKnora在所有核心数据表中都包含tenant_id字段来实现逻辑隔离 00-init-db.sql:9-22 。

每个租户的数据通过租户ID进行严格分离:

  • 租户表:存储租户基本信息和API密钥 00-init-db.sql:9-22
image
  • 知识库表 :通过tenant_id关联到特定租户 00-init-db.sql:49-61
image
  • 知识表:包含租户ID确保知识内容隔离 00-init-db.sql:67-90
  • 分块表:文档分块也按租户ID隔离 00-init-db.sql:124-148

同时我们看到数据库字段注释并不全面

租户数据结构设计

租户实体包含完整的隔离配置信息 tenant.go:11-37 :

  • 存储配额管理:每个租户有独立的存储配额和使用量统计
  • 检索引擎配置:支持租户级别的检索引擎参数定制 tenant.go:39-41
  • API密钥认证:每个租户拥有唯一的加密API密钥
数据访问隔离实现

所有数据访问操作都通过租户ID进行过滤 knowledge.go:31-39 :

  • 查询隔离 :所有数据库查询都包含tenant_id条件
  • 分页查询:支持租户级别的分页数据访问 knowledge.go:54-82
image
  • 批量操作:跨租户数据比较操作也严格按租户ID隔离 knowledge.go:170-187
image

还有SQL语句拼接,字段写死

上下文传递机制

系统通过上下文传递租户信息确保请求级别的隔离 message.go:46-52 :

  • 租户ID注入:认证中间件将租户ID注入到请求上下文
  • 服务层验证:所有服务层操作都从上下文获取租户ID进行验证
  • 跨服务调用:评估服务等跨服务调用也严格检查租户ID匹配 evaluation.go:111-124
存储配额管理

系统实现了租户级别的存储配额控制 tenant.go:65-82 :

  • 并发安全:使用悲观锁确保存储使用量更新的并发安全
  • 配额检查:防止存储使用量出现负值的业务规则验证
  • 动态调整:支持增量调整租户存储使用量
安全性缺陷
1. 单点失效风险

API Key 一旦泄露,攻击者即可获得完整的租户访问权限 auth.go:76-82 。系统没有实现细粒度的权限控制,所有操作都依赖同一个 API Key。

2. 缺乏会话管理

与传统的用户名/密码+会话机制不同,API Key 是长期有效的静态凭证 tenant.go:217-247 。没有会话过期、刷新令牌等安全机制。

3. 密钥轮换困难

虽然系统提供了 UpdateAPIKey 功能 tenant.go:184-215 ,但密钥更新需要手动操作,无法实现自动轮换,增加了管理负担。

数据库设计

E-R图

image

TENANTS: 租户实体,系统的顶层隔离单位 00-init-db.sql:9-22

MODELS: 模型配置实体,支持多种AI模型类型 00-init-db.sql:29-42

KNOWLEDGE_BASES: 知识库实体,知识管理的容器 00-init-db.sql:49-61

KNOWLEDGES: 知识实体,具体的文档或内容 00-init-db.sql:67-90

CHUNKS: 分块实体,文档的最小处理单位 00-init-db.sql:144-164

SESSIONS: 会话实体,用户交互的上下文 00-init-db.sql:99-120

MESSAGES: 消息实体,会话中的具体对话 00-init-db.sql:127-138

EMBEDDINGS: 向量嵌入实体,支持语义检索 00-init-db.sql:170-183

详细

image
image
image
image

总结

该项目属于微服务架构,涉及Golang与Python混合架构,也有Grpc通讯技术栈,模块划分还算清晰。但代码质量一般,大规模部署还有待性能测试。

支持多个不同类型LLM集成方式(本地与云端)。不支持信创体系,则政务类环境还需要改造。总体中规中矩,可以做为RAG项目进行学习与参考。

相关推荐
xcya2 分钟前
Java ReentrantLock 核心用法
后端
coder_pig11 分钟前
👦抠腚男孩的AI学习之旅 | 4、如何借助AI,高效学习,实现快速"跨域"
aigc·ai编程·cursor
用户4665370150514 分钟前
如何在 IntelliJ IDEA 中可视化压缩提交到生产分支
后端·github
小楓120120 分钟前
MySQL數據庫開發教學(一) 基本架構
数据库·后端·mysql
天天摸鱼的java工程师22 分钟前
Java 解析 JSON 文件:八年老开发的实战总结(从业务到代码)
java·后端·面试
白仑色24 分钟前
Spring Boot 全局异常处理
java·spring boot·后端·全局异常处理·统一返回格式
之诺29 分钟前
MySQL通信过程字符集转换
后端·mysql
喵手30 分钟前
反射机制:你真的了解它的“能力”吗?
java·后端·java ee
用户4665370150531 分钟前
git代码压缩合并
后端·github
武大打工仔35 分钟前
从零开始手搓一个MVC框架
后端