腾讯WeKnora 架构学习指南

本文涉及的产品
多模态交互后付费免费试用,全链路、全Agent
简介: 《WeKnora架构学习指南》系统解析了这一腾讯开源的智能知识库项目,涵盖核心架构、技术栈、代码结构与学习路径。通过生活化类比和深度流程图解,帮助开发者从零掌握Go后端、Vue前端、RAG原理及微服务协同,提供四阶段进阶路线与实战建议,助力快速上手并参与贡献。

WeKnora 架构学习指南 🎓

写在前面:你好!我是你的技术教练。这份指南将带你从零开始,深入理解 WeKnora 这个优秀的开源项目。别担心,我会用最通俗的方式,像聊天一样,一步步带你探索这个项目的精妙之处。准备好了吗?让我们开始这段激动人心的学习之旅!💪


第一部分:项目架构深度解析(像架构师一样俯瞰全景)🔍

1. 项目架构概览

💡 用一个生活化的类比来理解

想象一下,WeKnora 就像一个超级智能的图书馆管理系统

  • 前台接待员(Frontend):漂亮的 Vue.js 界面,你可以在这里上传文档、提出问题
  • 馆长助理(Go 后端):高效的 Go 服务,负责接待访客、分配任务、协调各部门
  • 资料整理员(Python DocReader):专门负责把各种格式的文档(PDF、Word、图片)整理成统一的格式
  • 索引系统(向量数据库):像图书馆的卡片目录,但更智能,能理解语义
  • 智能顾问(LLM):当你问问题时,它能结合检索到的资料给你专业的回答

这个比喻虽然简化了,但抓住了核心:WeKnora 就是让机器能像人类图书馆员一样,理解你的问题,找到相关资料,然后给出专业的回答。

🏗️ 核心设计特征

WeKnora 采用了现代化的分层架构 + 微服务理念,虽然不是完全的微服务架构,但已经实现了关注点分离:

  1. 表现层(Presentation Layer)

    • Vue 3 + TypeScript 前端
    • RESTful API 接口
    • SSE(Server-Sent Events)流式响应
  2. 应用层(Application Layer)

    • Handler:HTTP 请求处理
    • Service:业务逻辑编排
    • Repository:数据访问抽象
  3. 领域层(Domain Layer)

    • 核心业务模型
    • 接口定义(interfaces)
    • 业务规则
  4. 基础设施层(Infrastructure Layer)

    • 数据库(PostgreSQL + pgvector)
    • 缓存(Redis)
    • 消息队列(Asynq)
    • 对象存储(MinIO/COS)
    • 链路追踪(Jaeger)

🌟 与同类项目的对比

让我给你看看 WeKnora 的独特之处:

对比维度 WeKnora Dify FastGPT
核心语言 Go(高性能) Python TypeScript
文档处理 Python gRPC 服务 内置 Node.js
并发能力 ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐
知识图谱 ✅ GraphRAG 部分支持
链路追踪 ✅ OpenTelemetry 基础 基础
部署复杂度 中等 简单 简单
学习价值 Go 最佳实践 Python AI 应用 TS 全栈
背书 腾讯开源 初创公司 开源社区

WeKnora 的优势

  • 性能卓越:Go 的高并发特性,轻松应对大量请求
  • 架构清晰:严格的分层设计,适合学习企业级架构
  • 可观测性强:完整的链路追踪,问题排查超级方便
  • 技术栈现代:依赖注入、接口设计都是业界最佳实践
  • 腾讯背书:代码质量有保障,长期维护有信心

🔧 技术栈深度分析

来看看这些技术选型背后的考量:

后端技术栈(Go)

Go 1.24+ 
├── Web 框架: Gin (轻量、高性能)
├── ORM: GORM (类型安全、功能完整)
├── 依赖注入: uber/dig (企业级 IoC 容器)
├── 配置管理: Viper (灵活的配置方案)
├── 日志: logrus (结构化日志)
├── 链路追踪: OpenTelemetry (云原生标准)
├── 任务队列: asynq (Redis 支持的异步任务)
└── gRPC: google.golang.org/grpc (与 Python 服务通信)

为什么选 Go?

  1. 并发天生强大:goroutine 让处理上千并发请求变得轻而易举
  2. 性能接近 C:比 Python 快 10-100 倍,比 Node.js 快 2-5 倍
  3. 部署简单:编译成单个二进制文件,没有依赖地狱
  4. 适合后端服务:标准库强大,生态成熟

文档处理(Python)

Python 3.x
├── gRPC 服务
├── 文档解析库 (PyPDF2, python-docx 等)
├── OCR (可选,处理图片中的文字)
├── 图像理解 (VLM 模型)
└── Poetry 依赖管理

为什么文档处理用 Python?

  • 文档处理库生态成熟(PDF、Word、OCR)
  • AI/ML 库丰富(处理图像、调用视觉模型)
  • 开发效率高,适合快速迭代

前端技术栈(Vue 3)

Vue 3.5+
├── 构建工具: Vite 7
├── 状态管理: Pinia
├── 路由: Vue Router 4
├── UI 框架: TDesign (腾讯自家的 UI 库)
├── Markdown 渲染: marked
├── HTTP 客户端: axios
└── TypeScript (类型安全)

数据库和中间件

数据存储
├── PostgreSQL (ParadeDB 版本)
│   ├── pgvector (向量存储和检索)
│   └── 全文搜索扩展
├── Redis (缓存 + 任务队列)
└── MinIO (对象存储,S3 兼容)

检索引擎
├── PostgreSQL pgvector (默认)
└── Elasticsearch (可选,全文检索强项)

🎯 外部系统集成

WeKnora 设计了灵活的外部系统集成方案:

graph LR
    A[WeKnora 核心] --> B[LLM 服务]
    A --> C[Embedding 服务]
    A --> D[Rerank 服务]
    A --> E[存储服务]
    A --> F[向量数据库]

    B --> B1[Ollama 本地]
    B --> B2[OpenAI API]
    B --> B3[其他兼容 API]

    C --> C1[本地 Embedding]
    C --> C2[BGE API]
    C --> C3[GTE API]

    E --> E1[本地文件系统]
    E --> E2[MinIO]
    E --> E3[腾讯云 COS]

    F --> F1[PostgreSQL pgvector]
    F --> F2[Elasticsearch]

这种设计的好处

  • 🔄 可替换性:不喜欢 OpenAI?换成 Ollama 或其他模型即可
  • 🔒 私有化部署:可以完全本地化,数据不出门
  • 💰 成本可控:本地模型免费,API 按需付费
  • 🚀 灵活扩展:轻松接入新的模型和服务

📊 架构流程描述

让我带你走一遍完整的"用户提问 → 获得答案"的流程:

sequenceDiagram
    autonumber
    participant U as 👤 用户
    participant F as 🖥️ 前端
    participant A as 🔧 API网关
    participant S as 🧠 Session服务
    participant R as 🔍 检索器
    participant V as 📚 向量DB
    participant L as 🤖 LLM
    participant M as 💾 消息存储

    U->>F: 在对话界面输入问题
    F->>A: POST /api/v1/knowledge-chat/:session_id
    A->>A: 认证&授权检查
    A->>S: 转发到 SessionHandler.KnowledgeQA
    S->>S: 加载会话上下文

    alt 启用了问题改写
        S->>L: 基于历史对话改写问题
        L-->>S: 返回改写后的问题
    end

    S->>R: 调用检索器检索相关知识

    par 并行检索
        R->>R: BM25 关键词检索
        R->>V: 向量相似度检索
    end

    R->>R: 合并检索结果

    alt 启用了重排序
        R->>L: 调用 Rerank 模型重排序
        L-->>R: 返回排序后的结果
    end

    R-->>S: 返回 Top-K 相关文档片段
    S->>S: 构建提示词(问题+上下文+历史)
    S->>L: 调用 LLM 生成答案(流式)

    loop 流式返回
        L-->>S: 返回生成的 token
        S-->>F: SSE 推送 token
        F-->>U: 实时显示答案
    end

    L-->>S: 生成完成
    S->>M: 保存问题和答案到消息表
    S-->>F: 返回完成信号
    F-->>U: 显示完整答案

这个流程的关键点

  1. 认证授权(步骤 3):中间件自动处理,基于 JWT token
  2. 问题改写(步骤 5-6):解决代词指代问题,如"它怎么样" → "微信支付怎么样"
  3. 混合检索(步骤 8-9):BM25 + 向量检索,结合关键词和语义匹配
  4. 重排序(步骤 11-12):用更精确的模型对初筛结果重新排序
  5. 流式响应(步骤 15-18):用户不用等全部生成完,边生成边看
  6. 持久化(步骤 20):保存对话历史,支持多轮对话

整个流程耗时分析(以典型场景为例):

  • 检索阶段:50-200ms
  • Rerank 阶段:100-300ms(如果启用)
  • LLM 生成:1-5 秒(取决于答案长度)
  • 总计:约 2-6 秒首 token 返回

2. 目录结构与核心流程

好,现在让我们深入项目的"骨架"——目录结构。理解了目录组织,你就能快速定位任何功能的代码位置。

📁 目录组织逻辑

WeKnora 采用了按功能模块 + 按技术层次的混合组织方式:

WeKnora/
│
├── cmd/                          # 🚀 应用入口
│   └── server/
│       └── main.go              # ⭐ 从这里开始!程序启动入口
│
├── internal/                     # 🏠 核心业务逻辑(私有包)
│   ├── application/             # 应用层
│   │   ├── service/            # 🧠 业务逻辑服务
│   │   │   ├── chat_pipline/  # 对话流水线(核心!)
│   │   │   ├── knowledge.go   # 知识管理
│   │   │   ├── retriever/     # 检索器实现
│   │   │   └── ...
│   │   └── repository/         # 📊 数据访问层
│   │       ├── knowledge.go
│   │       └── retriever/      # 不同数据库的检索实现
│   │           ├── postgres/
│   │           └── elasticsearch/
│   │
│   ├── handler/                # 🎮 HTTP 请求处理器
│   │   ├── auth.go
│   │   ├── knowledge.go
│   │   ├── session.go          # ⭐ 对话相关的核心 handler
│   │   └── ...
│   │
│   ├── models/                 # 🤖 外部模型交互
│   │   ├── chat/              # LLM 调用
│   │   ├── embedding/         # 向量化模型
│   │   └── rerank/            # 重排序模型
│   │
│   ├── types/                  # 📝 类型定义
│   │   ├── interfaces/        # ⭐ 接口定义(依赖倒置)
│   │   ├── knowledge.go
│   │   └── ...
│   │
│   ├── config/                 # ⚙️ 配置管理
│   ├── container/              # 🏭 依赖注入容器
│   ├── middleware/             # 🛡️ 中间件
│   ├── router/                 # 🛤️ 路由定义
│   ├── tracing/                # 🔍 链路追踪初始化
│   └── utils/                  # 🔧 工具函数
│
├── services/                    # 🐍 独立微服务
│   └── docreader/              # Python 文档解析服务
│       └── src/
│           ├── grpc_server.py  # gRPC 服务端
│           └── parsers/        # 各种文档解析器
│
├── frontend/                    # 🎨 前端应用
│   └── src/
│       ├── views/              # 页面组件
│       ├── components/         # 可复用组件
│       ├── api/                # API 调用封装
│       └── stores/             # Pinia 状态管理
│
├── migrations/                  # 🗄️ 数据库迁移脚本
│   ├── mysql/
│   └── paradedb/               # ⭐ 推荐使用这个
│
├── config/                      # ⚙️ 配置文件
│   └── config.yaml             # ⭐ 核心配置(提示词模板在这里)
│
├── scripts/                     # 🛠️ 运维脚本
│   └── start_all.sh            # ⭐ 一键启动脚本
│
├── client/                      # 📦 Go SDK(可选)
├── mcp-server/                  # 🔌 MCP 协议服务器
├── dataset/                     # 📊 评估数据集工具
└── docs/                        # 📚 项目文档

🎯 关键文件定位

如果你只有 30 分钟快速了解项目,按这个顺序阅读

  1. 第一个必读 ⭐⭐⭐

    • README_CN.md - 项目总览
    • docker-compose.yml - 了解系统组成
    • cmd/server/main.go - 程序入口
  2. 理解业务流程 ⭐⭐⭐

    • internal/router/router.go - API 路由定义
    • internal/handler/session.go - 对话处理
    • internal/application/service/chat_pipline/chat_pipline.go - 对话流水线
  3. 理解数据模型 ⭐⭐

    • internal/types/knowledge.go - 知识库相关类型
    • internal/types/session.go - 会话相关类型
    • migrations/paradedb/00-init-db.sql - 数据库表结构
  4. 理解配置 ⭐⭐

    • config/config.yaml - 核心配置(提示词模板超重要!)
    • internal/config/config.go - 配置加载逻辑

🔗 模块依赖关系

让我用图表清晰展示模块间的依赖关系:

graph TB
    subgraph 表现层
        H[Handler]
    end

    subgraph 应用层
        S[Service]
        R[Repository]
    end

    subgraph 领域层
        I[Interfaces]
        T[Types]
    end

    subgraph 基础设施层
        M[Models<br/>LLM/Embedding]
        D[Database]
        C[Cache/MQ]
    end

    H --> S
    S --> R
    S --> M
    R --> D
    S --> C

    H -.依赖.-> I
    S -.依赖.-> I
    R -.依赖.-> I

    H --> T
    S --> T
    R --> T

    style I fill:#e1f5ff
    style T fill:#fff3e0

这种依赖关系的优点

  • 单向依赖:高层模块依赖低层模块,但通过接口解耦
  • 易于测试:可以轻松 mock 接口进行单元测试
  • 易于替换:比如换数据库,只需实现新的 Repository 接口
  • 符合 SOLID 原则:特别是依赖倒置原则(DIP)

依赖注入容器的作用

看看 internal/container/container.go,你会发现它使用 uber/dig 自动管理所有依赖:

// 伪代码示例
container := dig.New()

// 注册依赖
container.Provide(NewDatabase)      // 数据库连接
container.Provide(NewRepository)    // 仓储层
container.Provide(NewService)       // 服务层
container.Provide(NewHandler)       // 处理器层

// 自动解析依赖并调用
container.Invoke(func(handler *Handler) {
   
    // handler 的所有依赖都已自动注入
})

这就像是一个智能工厂,你只需要声明"我需要什么",容器会自动帮你创建并注入依赖,不需要手动 new 一大堆对象。

🔄 典型业务流程:知识问答全链路

让我选择最核心的业务场景——用户上传文档并进行问答——来展示数据流和控制流:

场景描述:用户上传了一份《微信支付接入指南.pdf》,然后问"如何申请商户号?"

完整流程拆解

第一阶段:文档上传与处理 📤
sequenceDiagram
    autonumber
    participant U as 用户
    participant F as 前端
    participant KH as KnowledgeHandler
    participant KS as KnowledgeService
    participant FS as FileStorage
    participant DR as DocReader(gRPC)
    participant CS as ChunkService
    participant EM as Embedding模型
    participant VDB as 向量数据库

    U->>F: 选择文件并上传
    F->>KH: POST /api/v1/knowledge-bases/:id/knowledge/file
    KH->>FS: 保存文件到存储(MinIO/COS)
    FS-->>KH: 返回文件 URL
    KH->>DR: gRPC 调用:解析文档
    DR->>DR: 识别文档类型并解析
    DR->>DR: OCR 提取图片文字
    DR-->>KH: 返回解析后的文本和图片
    KH->>CS: 文本分块(ChunkService)
    CS->>CS: 按策略切分(512字/块,重叠50字)
    CS->>EM: 批量调用 Embedding 模型
    EM-->>CS: 返回向量表示
    CS->>VDB: 批量插入向量数据库
    VDB-->>CS: 插入成功
    CS-->>KH: 文档处理完成
    KH-->>F: 返回成功状态
    F-->>U: 显示"文档已处理"

核心代码位置

  • 文件上传:internal/handler/knowledge.go - CreateKnowledgeFromFile()
  • 文档解析:services/docreader/src/grpc_server.py - ParseDocument()
  • 文本分块:internal/application/service/chunk.go - CreateChunks()
  • 向量化:internal/models/embedding/ 各实现
  • 存储:internal/application/repository/chunk.go - CreateBatch()

这个阶段的关键技术点

  1. gRPC 跨语言调用:Go 调用 Python 服务

    // Go 端
    conn, _ := grpc.Dial("docreader:50051")
    client := pb.NewDocReaderClient(conn)
    response, _ := client.ParseDocument(ctx, &pb.ParseRequest{
         ...})
    
  2. 文本分块策略

    • 默认 512 个字符一块
    • 重叠 50 个字符(保持上下文连贯)
    • 按段落、句子优先切分(不会切断句子)
  3. 批量向量化

    • 不是一条一条调用 Embedding API
    • 而是批量调用(比如 32 条一批)
    • 大幅提升效率,降低成本
  4. 异步处理

    • 文档上传后立即返回
    • 后台使用 Asynq 任务队列异步处理
    • 用户可以查看处理进度
第二阶段:用户问答 💬
sequenceDiagram
    autonumber
    participant U as 用户
    participant F as 前端
    participant SH as SessionHandler
    participant CP as ChatPipeline
    participant RW as Rewriter
    participant RT as Retriever
    participant RK as Reranker
    participant LLM as LLM模型
    participant MS as MessageService

    U->>F: 输入"如何申请商户号?"
    F->>SH: POST /knowledge-chat/:session_id
    SH->>SH: 加载会话上下文
    SH->>CP: 启动对话流水线

    alt 问题需要改写
        CP->>RW: 改写问题(补全指代)
        RW->>LLM: 调用 LLM 改写
        LLM-->>RW: 返回改写结果
        RW-->>CP: 改写后的问题
    end

    CP->>RT: 混合检索

    par BM25 关键词检索
        RT->>RT: 分词:[申请, 商户号]
        RT->>RT: BM25 算法打分
    and 向量语义检索
        RT->>EM: 问题向量化
        EM-->>RT: 问题向量
        RT->>VDB: 相似度检索
        VDB-->>RT: Top-30 候选
    end

    RT->>RT: 合并去重

    alt 启用重排序
        RT->>RK: 重排序
        RK->>LLM: 调用 Rerank 模型
        LLM-->>RK: 重排后的结果
        RK-->>RT: Top-5 最相关片段
    end

    RT-->>CP: 返回相关文档片段
    CP->>CP: 构建完整提示词
    CP->>LLM: 流式调用 LLM

    loop 流式返回
        LLM-->>CP: 返回 token
        CP-->>SH: SSE 推送
        SH-->>F: 推送给前端
        F-->>U: 实时显示
    end

    CP->>MS: 保存消息记录
    CP-->>SH: 完成信号

核心代码位置

  • 对话入口:internal/handler/session.go - KnowledgeQA()
  • 流水线编排:internal/application/service/chat_pipline/chat_pipline.go
  • 问题改写:internal/application/service/chat_pipline/rewrite.go
  • 检索器:internal/application/service/retriever/keywords_vector_hybrid_indexer.go
  • LLM 调用:internal/models/chat/ 各实现

这个阶段的关键技术点

  1. 问题改写(Query Rewrite)

    原问题:"它安全吗?"
    历史对话:"微信支付有哪些功能?"
    改写后:"微信支付安全吗?"
    

    这样做的好处是让检索更准确!

  2. 混合检索(Hybrid Retrieval)

    • BM25(关键词):精确匹配,如"商户号"、"申请"
    • 向量检索(语义):语义相似,如"注册"也能匹配"申请"
    • 加权合并score = 0.3 * bm25_score + 0.7 * vector_score
  3. 重排序(Rerank)
    为什么需要?因为初筛的 30 条结果质量参差不齐,用更强大的模型再精排一次,选出最佳的 5 条。

  4. 流式响应(Streaming)

    • 不是等 LLM 生成完整答案再返回
    • 而是每生成一个 token 就立即推送给前端
    • 用户体验更好,感觉更快
  5. 上下文窗口管理

    完整提示词 =
      系统提示词 +
      历史对话(最近 5 轮)+
      检索到的文档片段(Top 5)+
      用户当前问题
    

    总长度不能超过模型的上下文限制(如 8k tokens)

📄 实现文件索引

为了方便你快速定位代码,这里给出一个功能 → 文件的映射表:

功能模块 核心文件 说明
应用启动 cmd/server/main.go 程序入口
路由定义 internal/router/router.go 所有 API 路由
认证授权 internal/middleware/auth.go JWT 验证
知识库管理 internal/handler/knowledgebase.go 创建、查询知识库
文档上传 internal/handler/knowledge.go 文件上传和处理
对话问答 internal/handler/session.go 问答核心逻辑
对话流水线 internal/application/service/chat_pipline/chat_pipline.go 编排各个步骤
文本分块 internal/application/service/chunk.go 分块策略
混合检索 internal/application/service/retriever/keywords_vector_hybrid_indexer.go BM25 + 向量
PostgreSQL 检索 internal/application/repository/retriever/postgres/repository.go pgvector 实现
Elasticsearch 检索 internal/application/repository/retriever/elasticsearch/v8/repository.go ES 实现
LLM 调用(Ollama) internal/models/chat/ollama.go 本地模型
LLM 调用(API) internal/models/chat/remote_api.go 远程 API
Embedding 模型 internal/models/embedding/ 各种实现
Rerank 模型 internal/models/rerank/ 重排序
文档解析服务 services/docreader/src/grpc_server.py Python gRPC
前端对话页面 frontend/src/views/chat/ Vue 组件

3. 代码结构观察

现在让我们从代码质量的角度来审视这个项目。作为学习者,了解优秀代码的特征,也能帮你识别可以改进的地方。

✅ 代码组织模式

WeKnora 的代码组织体现了多个优秀的设计模式:

1. 依赖倒置原则(DIP)

internal/types/interfaces/ 目录,你会发现大量的接口定义:

// internal/types/interfaces/knowledge_base.go
type KnowledgeBaseService interface {
   
    Create(ctx context.Context, req *types.CreateKnowledgeBaseRequest) (*types.KnowledgeBase, error)
    Get(ctx context.Context, id string) (*types.KnowledgeBase, error)
    // ...更多方法
}

高层模块(Handler)依赖接口,而不是具体实现(Service)。这样的好处:

  • ✅ 易于测试:可以轻松 mock
  • ✅ 易于替换:换实现不影响调用方
  • ✅ 解耦合:模块间独立开发

2. 工厂模式(Factory Pattern)

检索器的创建使用了工厂模式:

// internal/application/service/retriever/registry.go
func NewRetriever(dbType string, ...) Retriever {
   
    switch dbType {
   
    case "postgres":
        return NewPostgresRetriever(...)
    case "elasticsearch":
        return NewElasticsearchRetriever(...)
    default:
        panic("unsupported database type")
    }
}

通过配置文件就能切换不同的检索实现,无需修改代码!

3. 构建者模式(Builder Pattern)

LLM 请求的构建:

// 伪代码示例
request := NewChatRequest().
    WithModel("qwen").
    WithMessages(messages).
    WithTemperature(0.7).
    WithStream(true).
    Build()

链式调用,代码优雅易读。

4. 策略模式(Strategy Pattern)

不同的检索策略可以灵活组合:

// 组合检索器
retriever := NewCompositeRetriever().
    Add(NewBM25Retriever(), 0.3).      // 30% 权重
    Add(NewVectorRetriever(), 0.7).    // 70% 权重
    Build()

🎨 设计模式识别

让我帮你识别项目中的设计模式,这些都是面试高频考点!

设计模式 使用场景 代码位置 优势
单例模式 数据库连接 internal/container/ 全局唯一实例
工厂模式 检索器创建 internal/application/service/retriever/registry.go 解耦创建逻辑
策略模式 检索策略 internal/application/service/retriever/ 算法可替换
装饰器模式 中间件链 internal/middleware/ 动态添加功能
观察者模式 流式响应 SSE 推送 事件驱动
模板方法 对话流水线 chat_pipline.go 固定流程,灵活步骤
适配器模式 不同 LLM 接口 internal/models/chat/ 统一接口
责任链模式 中间件处理 Gin 中间件 链式处理请求

📏 代码质量观察

作为学习者,让我们客观地评估代码质量:

优点 ✅:

  1. 目录结构清晰:按功能和层次组织,易于导航
  2. 接口设计良好:大量使用接口,符合 SOLID 原则
  3. 注释适度:关键逻辑有注释,不过度注释
  4. 错误处理规范:统一的错误处理和日志记录
  5. 配置灵活:YAML + 环境变量,适应不同环境
  6. 类型安全:充分利用 Go 的类型系统

可以改进的地方 💡(学习机会):

  1. 单元测试覆盖

    • 当前状态:部分核心模块有测试,但覆盖率不够高
    • 学习机会:可以为关键服务补充测试用例
    • 文件示例:internal/application/service/chat_pipline/chat_pipline_test.go
  2. 文档注释

    • 当前状态:大部分函数有注释,但有些不够详细
    • 学习机会:可以按 Go 的文档规范补充注释
    • 参考:Go Doc Comments
  3. 配置管理

    • 当前状态:配置在 YAML 文件中,修改需重启
    • 改进方向:可以支持配置热更新(如使用 Viper 的 WatchConfig)
    • 学习机会:实现一个配置热加载功能
  4. API 文档

    • 当前状态:有 docs/API.md,但不是自动生成
    • 改进方向:可以集成 Swagger/OpenAPI
    • 学习机会:添加 Swagger 注解并自动生成文档
  5. 性能监控

    • 当前状态:有链路追踪,但缺少详细的性能指标
    • 改进方向:可以添加 Prometheus metrics
    • 学习机会:集成 Prometheus + Grafana 监控

🔍 潜在改进点(学习机会)

作为学习者,你可以通过改进这些地方来深入理解项目:

初级练习 🌱:

  1. 补充单元测试

    • 选择一个 Service 层的函数
    • 编写完整的测试用例(正常情况 + 异常情况)
    • 学习:如何 mock 依赖、如何编写好测试
  2. 优化错误信息

    • 搜索代码中的 error 返回
    • 确保每个错误都有清晰的上下文信息
    • 学习:Go 的错误处理最佳实践
  3. 改进日志输出

    • 统一日志格式
    • 添加结构化字段(如 user_id, knowledge_base_id
    • 学习:结构化日志的重要性

中级练习 🌿:

  1. 实现一个新的检索器

    • 比如集成 Weaviate 向量数据库
    • 实现 Retriever 接口
    • 学习:如何扩展系统功能
  2. 添加缓存层

    • 对热门问题的答案进行缓存
    • 使用 Redis 实现
    • 学习:缓存策略和失效机制
  3. 实现配置热更新

    • 修改提示词模板无需重启服务
    • 使用 Viper 的 WatchConfig
    • 学习:配置管理和文件监听

高级练习 🌳:

  1. 实现分布式追踪的详细分析

    • 在每个关键步骤添加 Span
    • 记录详细的性能指标
    • 学习:OpenTelemetry 的深度使用
  2. 实现多租户隔离

    • 不同租户的数据物理隔离
    • 实现租户级别的资源配额
    • 学习:多租户架构设计
  3. 实现知识图谱可视化

    • 前端展示实体关系图
    • 支持交互式探索
    • 学习:图数据库和可视化技术

第二部分:技能需求清单(你的学习弹药库)📚

好了,了解了项目架构后,你可能在想:"我需要掌握哪些技能才能真正理解和贡献这个项目?"别着急,我帮你梳理了一份完整的技能清单。

1. 基础技能要求

这些是你必须掌握的基础技能,没有这些基础,后面的学习会很吃力。

🔤 编程语言和框架

Go 语言(核心,必须精通) ⭐⭐⭐⭐⭐

你需要掌握的 Go 特性:

  1. 基础语法

    • 变量、常量、类型系统
    • 控制流(if、for、switch)
    • 函数、方法、闭包
    • 指针和值传递
  2. 数据结构

    • 数组、切片(slice)、map
    • 结构体(struct)
    • 接口(interface)—— ⭐ 超级重要!
  3. 并发编程 ⭐ 核心特性:

    • Goroutine:轻量级线程
    • Channel:goroutine 间通信
    • Select:多路复用
    • Mutex、RWMutex:互斥锁
    • WaitGroup:等待多个 goroutine 完成
  4. 错误处理

    // Go 的错误处理模式
    result, err := DoSomething()
    if err != nil {
         
        return fmt.Errorf("do something failed: %w", err)
    }
    
  5. 包管理

    • Go Modules(go.mod、go.sum)
    • 导入和导出规则(大写字母开头才能被外部访问)

版本要求:Go 1.24+(项目使用了最新特性)

学习路径

  • 📘 官方教程:A Tour of Go
  • 📘 进阶阅读:《Effective Go》(官方最佳实践)
  • 📘 深入理解:《Go 语言高级编程》

Gin Web 框架 ⭐⭐⭐⭐

WeKnora 使用 Gin 作为 Web 框架,你需要掌握:

  1. 路由和处理器

    r := gin.Default()
    r.GET("/api/users/:id", handler.GetUser)
    r.POST("/api/users", handler.CreateUser)
    
  2. 中间件

    r.Use(middleware.Logger())
    r.Use(middleware.Auth())
    
  3. 参数绑定

    var req CreateUserRequest
    if err := c.ShouldBindJSON(&req); err != nil {
         
        c.JSON(400, gin.H{
         "error": err.Error()})
        return
    }
    
  4. 响应处理:JSON、文件下载、流式响应等

学习资源Gin 官方文档

GORM(数据库 ORM) ⭐⭐⭐

WeKnora 使用 GORM 进行数据库操作:

  1. 模型定义

    type Knowledge struct {
         
        ID        string    `gorm:"primaryKey"`
        Title     string    `gorm:"type:varchar(255)"`
        CreatedAt time.Time
    }
    
  2. CRUD 操作

    // 创建
    db.Create(&knowledge)
    // 查询
    db.Where("title = ?", "test").First(&knowledge)
    // 更新
    db.Model(&knowledge).Update("status", "processed")
    // 删除
    db.Delete(&knowledge)
    
  3. 关联查询

    db.Preload("Chunks").Find(&knowledges)
    

学习资源GORM 官方文档

🌐 前端基础(了解即可)

如果你想修改前端界面,需要了解:

Vue 3 ⭐⭐⭐

  1. 组合式 API(Composition API)

    <script setup lang="ts">
    import { ref, onMounted } from 'vue'
    
    const message = ref('Hello')
    
    onMounted(() => {
        console.log('Component mounted')
    })
    </script>
    
  2. 响应式数据refreactivecomputed

  3. 路由:Vue Router
  4. 状态管理:Pinia(Vue 3 的官方状态管理)

TypeScript ⭐⭐

  • 基本类型注解
  • 接口和类型别名
  • 泛型基础

学习资源Vue 3 官方文档

🗄️ 数据库和 SQL

PostgreSQL ⭐⭐⭐⭐

  1. 基础 SQL

    • SELECT、INSERT、UPDATE、DELETE
    • JOIN 查询
    • 索引和性能优化
  2. PostgreSQL 特性

    • JSON/JSONB 类型
    • 全文搜索(to_tsvector、to_tsquery)
    • pgvector 扩展 ⭐ 向量检索的核心!
  3. pgvector 基本用法

    -- 创建向量列
    ALTER TABLE chunks ADD COLUMN embedding vector(768);
    
    -- 创建向量索引
    CREATE INDEX ON chunks USING ivfflat (embedding vector_cosine_ops);
    
    -- 向量相似度查询
    SELECT * FROM chunks
    ORDER BY embedding <=> '[0.1, 0.2, ...]'::vector
    LIMIT 10;
    

学习资源

Redis(缓存与消息队列) ⭐⭐⭐

  1. 基本数据类型:String、Hash、List、Set、ZSet
  2. 常用命令:GET/SET、EXPIRE、LPUSH/RPOP 等
  3. 发布订阅:用于流式响应管理
  4. 持久化:RDB 和 AOF

学习资源Redis 中文文档

🐳 容器化和部署

Docker ⭐⭐⭐⭐

  1. 基础概念

    • 镜像(Image)vs 容器(Container)
    • Dockerfile 编写
    • 容器网络和数据卷
  2. 常用命令

    docker build -t myapp .
    docker run -p 8080:8080 myapp
    docker ps
    docker logs -f container_id
    docker exec -it container_id bash
    

Docker Compose ⭐⭐⭐⭐

  1. docker-compose.yml 语法
  2. 服务编排:depends_on、networks、volumes
  3. 常用命令
    docker compose up -d
    docker compose down
    docker compose logs -f service_name
    docker compose restart service_name
    

学习资源Docker 官方文档

🔧 基础工具和概念

Git 版本控制 ⭐⭐⭐⭐

  • 基本操作:clone、add、commit、push、pull
  • 分支管理:branch、checkout、merge
  • 查看历史:log、diff、blame
  • 协作流程:PR、Code Review

HTTP 协议 ⭐⭐⭐

  • 请求方法:GET、POST、PUT、DELETE
  • 状态码:2xx、4xx、5xx
  • 请求头和响应头
  • RESTful API 设计规范

JSON 数据格式 ⭐⭐⭐

  • JSON 语法
  • 序列化和反序列化
  • Go 中的 encoding/json

2. 进阶技能要求

这些技能会帮助你深入理解项目的核心技术。

🤖 AI/ML 相关概念

RAG(Retrieval-Augmented Generation) ⭐⭐⭐⭐⭐

这是 WeKnora 的核心理念!

  1. 什么是 RAG?

    传统 LLM:问题 → LLM → 答案(可能幻觉)
    RAG 模式:问题 → 检索相关文档 → 问题+文档 → LLM → 答案(基于事实)
    
  2. RAG 的三个阶段

    • 索引阶段:文档分块 → 向量化 → 存储到向量数据库
    • 检索阶段:问题向量化 → 相似度搜索 → 返回 Top-K 文档
    • 生成阶段:问题+检索文档 → LLM → 生成答案
  3. 为什么需要 RAG?

    • ❌ LLM 的知识有截止日期,不知道最新信息
    • ❌ LLM 容易"胡编乱造"(幻觉问题)
    • ❌ LLM 不知道你的私有数据
    • ✅ RAG 让 LLM 基于你的文档回答,准确可控

学习资源

  • LangChain RAG 教程
  • 论文:《Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks》

Embedding(文本向量化) ⭐⭐⭐⭐

  1. 什么是 Embedding?

    • 把文本转换成高维向量(如 768 维)
    • 语义相似的文本,向量也相似
      "苹果手机" → [0.2, -0.5, 0.8, ..., 0.1]  (768维)
      "iPhone"   → [0.3, -0.4, 0.7, ..., 0.2]  (相似!)
      "香蕉"     → [0.1, 0.9, -0.3, ..., -0.5] (不相似)
      
  2. 常用 Embedding 模型

    • 中文:BGE、GTE、M3E
    • 英文:OpenAI text-embedding-3、Sentence-BERT
    • 多语言:M-BERT、XLM-RoBERTa
  3. 向量维度选择

    • 384维:速度快,精度一般
    • 768维:平衡(WeKnora 默认)
    • 1024维+:精度高,但更慢更耗资源

向量检索 ⭐⭐⭐⭐

  1. 相似度计算

    • 余弦相似度(Cosine Similarity):最常用
    • 欧氏距离(Euclidean Distance)
    • 点积(Dot Product)
  2. 向量索引算法

    • 暴力搜索(Brute Force):精确但慢
    • HNSW:速度快,精度高(推荐)
    • IVF(Inverted File Index):适合大规模数据
    • PQ(Product Quantization):压缩向量,节省内存
  3. 实际使用

    # 问题向量化
    query_vector = embedding_model.encode("如何申请商户号?")
    
    # 向量检索
    results = vector_db.search(
        vector=query_vector,
        top_k=10,
        similarity_threshold=0.7
    )
    

BM25 算法 ⭐⭐⭐

  1. 什么是 BM25?

    • 一种基于关键词的检索算法
    • TF-IDF 的改进版
    • 考虑词频、逆文档频率、文档长度
  2. BM25 vs 向量检索
    | 维度 | BM25 | 向量检索 |
    | -------- | -------------- | -------- |
    | 精确匹配 | ✅ 很好 | ❌ 较差 |
    | 语义理解 | ❌ 不行 | ✅ 很好 |
    | 速度 | 🚀 极快 | 🐢 较慢 |
    | 适用场景 | 专业术语、代码 | 自然语言 |

  3. 混合检索(WeKnora 的做法):

    最终得分 = 0.3 × BM25得分 + 0.7 × 向量相似度
    

    综合两者优势!

Rerank(重排序) ⭐⭐⭐

  1. 为什么需要 Rerank?

    • 初筛(BM25+向量)召回 30 条候选
    • 但质量参差不齐
    • 用更精确的模型重新排序,选出最佳 5 条
  2. Rerank 模型

    • BGE Reranker
    • Cohere Rerank
    • 自定义交叉编码器
  3. 性能对比

    只用向量检索:准确率 60%
    向量检索 + Rerank:准确率 85%+
    

    提升显著!

LLM API 调用 ⭐⭐⭐

  1. 主流 LLM 提供商

    • OpenAI(GPT-4、GPT-3.5)
    • 阿里云(通义千问)
    • 字节跳动(豆包)
    • 本地部署(Ollama + Qwen/Llama)
  2. API 基本参数

    {
         
      "model": "qwen-plus",
      "messages": [...],
      "temperature": 0.7,     // 创造性(0-2"max_tokens": 2000,     // 最大生成长度
      "stream": true          // 流式响应
    }
    
  3. 流式响应(Streaming)

    // 服务器推送事件(SSE)
    stream, _ := client.CreateChatCompletion(req)
    for {
         
        response, err := stream.Recv()
        if err == io.EOF {
         
            break
        }
        fmt.Print(response.Choices[0].Delta.Content)
    }
    

🏗️ 架构模式和设计原则

分层架构(Layered Architecture) ⭐⭐⭐⭐

表现层(Presentation Layer)   ← HTTP 请求处理
      ↓
应用层(Application Layer)     ← 业务逻辑编排
      ↓
领域层(Domain Layer)          ← 核心业务模型
      ↓
基础设施层(Infrastructure)    ← 数据库、外部服务

SOLID 原则 ⭐⭐⭐⭐

WeKnora 严格遵循 SOLID 原则:

  1. S - 单一职责原则(SRP)

    • 一个类只做一件事
    • 示例:ChunkService 只负责分块,不处理存储
  2. O - 开闭原则(OCP)

    • 对扩展开放,对修改关闭
    • 示例:新增检索器不需要修改现有代码
  3. L - 里氏替换原则(LSP)

    • 子类可以替换父类
    • 示例:PostgresRetriever 可以替换 Retriever 接口
  4. I - 接口隔离原则(ISP)

    • 不依赖不需要的接口
    • 示例:只定义必要的方法
  5. D - 依赖倒置原则(DIP) ⭐ 最重要!

    • 依赖接口,不依赖实现
    • WeKnora 大量使用接口

依赖注入(Dependency Injection) ⭐⭐⭐⭐

  1. 什么是依赖注入?

    // ❌ 不好:直接创建依赖
    type UserService struct {
         
        repo *UserRepository  // 硬编码依赖
    }
    func NewUserService() *UserService {
         
        return &UserService{
         
            repo: &UserRepository{
         },  // 紧耦合!
        }
    }
    
    // ✅ 好:注入依赖
    type UserService struct {
         
        repo UserRepositoryInterface  // 依赖接口
    }
    func NewUserService(repo UserRepositoryInterface) *UserService {
         
        return &UserService{
         repo: repo}  // 解耦!
    }
    
  2. WeKnora 使用 uber/dig

    container := dig.New()
    
    // 注册依赖
    container.Provide(NewDatabase)
    container.Provide(NewRepository)
    container.Provide(NewService)
    
    // 自动注入
    container.Invoke(func(svc *Service) {
         
        svc.DoSomething()
    })
    

领域驱动设计(DDD) ⭐⭐⭐

WeKnora 的部分设计借鉴了 DDD:

  1. 实体(Entity):如 KnowledgeChunk
  2. 值对象(Value Object):如 Embedding
  3. 聚合根(Aggregate Root):如 KnowledgeBase
  4. 仓储(Repository):数据访问抽象
  5. 服务(Service):业务逻辑编排

🔍 可观测性技术

链路追踪(Distributed Tracing) ⭐⭐⭐⭐

  1. OpenTelemetry

    • 云原生标准
    • 支持多种后端(Jaeger、Zipkin)
  2. 基本概念

    • Trace:一次完整的请求链路
    • Span:链路中的一个操作
    • Context Propagation:跨服务传递追踪信息
  3. 实际使用

    ctx, span := tracer.Start(ctx, "operation-name")
    defer span.End()
    
    // 添加属性
    span.SetAttributes(
        attribute.String("knowledge_id", id),
        attribute.Int("chunk_count", count),
    )
    
  4. 查看追踪

    • 访问 http://localhost:16686 查看 Jaeger UI
    • 可以看到每个请求的完整调用链
    • 定位性能瓶颈超级方便!

结构化日志 ⭐⭐⭐

  1. 为什么需要结构化日志?

    ❌ 纯文本:User 123 created knowledge
    ✅ 结构化:{"level":"info","user_id":"123","action":"create","resource":"knowledge"}
    

    结构化日志易于搜索和分析!

  2. WeKnora 使用 logrus

    log.WithFields(log.Fields{
         
        "user_id":    userID,
        "knowledge_id": knowledgeID,
    }).Info("Knowledge created")
    

消息队列(Message Queue) ⭐⭐⭐

  1. Asynq

    • 基于 Redis 的异步任务队列
    • 支持任务重试、定时任务
  2. 使用场景

    • 文档解析(耗时操作)
    • 向量化处理(批量任务)
    • 定时清理(周期任务)
  3. 基本用法

    // 生产者
    client := asynq.NewClient(redisOpt)
    task := asynq.NewTask("parse_document", payload)
    client.Enqueue(task)
    
    // 消费者
    srv := asynq.NewServer(redisOpt, asynq.Config{
         
        Concurrency: 10,
    })
    srv.HandleFunc("parse_document", handleParseDocument)
    srv.Run()
    

3. 技能掌握程度建议

根据你的学习目标,我给出不同阶段的建议:

🌱 初学者(刚接触 Go 和 Web 开发)

学习侧重

  1. Go 语言基础 - 必须精通
  2. Gin 框架 - 理解路由和中间件
  3. PostgreSQL - 基本 SQL 操作
  4. Docker - 会用 docker compose 启动项目
  5. Git - 基本的 clone、commit、push

能达到的目标

  • ✅ 能成功运行项目
  • ✅ 能修改简单的业务逻辑
  • ✅ 能添加新的 API 接口
  • ✅ 能调整配置参数

不需要掌握(暂时):

  • ❌ RAG 原理(知道概念即可)
  • ❌ 向量检索算法细节
  • ❌ OpenTelemetry 使用
  • ❌ 复杂的设计模式

学习时间估计:2-3 个月

🌿 有经验的开发者(熟悉一门后端语言)

学习侧重

  1. Go 特有特性 - 并发编程、接口设计
  2. 分层架构 - 理解各层职责
  3. RAG 原理 - 深入理解检索增强生成
  4. 向量检索 - 理解 Embedding 和相似度计算
  5. 依赖注入 - 理解 uber/dig 的用法

能达到的目标

  • ✅ 能理解核心业务流程
  • ✅ 能实现新的检索策略
  • ✅ 能集成新的 LLM 模型
  • ✅ 能优化性能瓶颈
  • ✅ 能修复大部分 Bug

应该掌握

  • ✅ SOLID 原则
  • ✅ 设计模式(工厂、策略、装饰器)
  • ✅ 单元测试编写
  • ✅ 链路追踪基本使用

学习时间估计:4-6 周

🌳 进阶贡献者(想深度参与开发)

学习侧重

  1. 系统设计 - 理解整体架构权衡
  2. 性能优化 - 识别和解决性能问题
  3. 可观测性 - OpenTelemetry 深度使用
  4. 分布式系统 - 理解分布式追踪、一致性等
  5. 领域知识 - RAG、NLP、向量检索的最新进展

能达到的目标

  • ✅ 能设计和实现大功能
  • ✅ 能做架构级别的优化
  • ✅ 能指导其他开发者
  • ✅ 能解决复杂的系统问题
  • ✅ 能贡献高质量的 PR

应该掌握

  • ✅ DDD(领域驱动设计)
  • ✅ CQRS(命令查询职责分离)
  • ✅ 事件驱动架构
  • ✅ 性能调优技巧
  • ✅ 生产环境最佳实践

学习时间估计:持续学习


第三部分:学习路径规划(你的专属教练计划)🎯

现在到了最激动人心的部分——让我们开始动手!我会带你一步步从零开始,逐渐深入。

1. 项目运行入口定位(快速上手)

🚀 一键启动指南(目标:30 分钟内运行起来)

前置条件检查

在开始之前,确保你的环境满足以下要求:

工具 最低版本 检查命令 安装链接
Docker 20.10+ docker --version docker.com
Docker Compose 2.0+ docker compose version 随 Docker Desktop 安装
Git 2.30+ git --version git-scm.com
磁盘空间 10GB+ - 清理空间
内存 8GB+ - 关闭其他应用

具体操作步骤 📝

# 步骤 1:克隆项目(约 1-2 分钟)
git clone https://github.com/Tencent/WeKnora.git
cd WeKnora

# 步骤 2:配置环境变量(约 2-3 分钟)
# Windows用户
copy .env.example .env
# Mac/Linux用户
cp .env.example .env

# 用记事本或VS Code打开 .env 文件,进行以下关键配置:
# DB_USER=weknora
# DB_PASSWORD=your_strong_password  ← 改成你自己的密码
# DB_NAME=weknora
# REDIS_PASSWORD=your_redis_password  ← 改成你自己的密码

# 步骤 3:一键启动所有服务(约 10-15 分钟,首次需要下载镜像)
./scripts/start_all.sh
# 或者 Windows 用户(如果上面不行)
docker compose up -d

# 步骤 4:查看服务状态
docker compose ps

预期输出(所有服务都应该是 Up 状态):

NAME                    STATUS          PORTS
WeKnora-app             Up (healthy)    0.0.0.0:8080->8080/tcp
WeKnora-frontend        Up              0.0.0.0:80->80/tcp
WeKnora-postgres        Up (healthy)    0.0.0.0:5432->5432/tcp
WeKnora-redis           Up              0.0.0.0:6379->6379/tcp
WeKnora-minio           Up              0.0.0.0:9000-9001->9000-9001/tcp
WeKnora-docreader       Up (healthy)    0.0.0.0:50051->50051/tcp
jaeger                  Up              0.0.0.0:16686->16686/tcp

步骤 5:验证成功

打开浏览器,访问以下地址:

  1. 前端页面http://localhost

    • 应该看到 WeKnora 的登录/初始化页面
    • 首次访问会自动跳转到初始化配置页面
  2. 后端 APIhttp://localhost:8080/health

    • 应该返回:{"status":"ok"}
  3. Jaeger 追踪http://localhost:16686

    • 应该看到 Jaeger UI 界面
  4. MinIO 控制台(可选):http://localhost:9001

    • 用户名:minioadmin
    • 密码:minioadmin

如果一切正常,恭喜你!🎉 你已经成功运行起 WeKnora 了!


⚠️ 常见环境配置陷阱及解决方案

根据社区反馈和我的经验,这里是最容易踩的坑:

陷阱 1:端口被占用 🔴

现象

Error: bind: address already in use

原因:默认端口(80、8080、5432等)已被其他程序占用

解决方案

# 方案1:找出并关闭占用端口的程序
# Windows
netstat -ano | findstr :80
taskkill /PID <进程ID> /F

# Mac/Linux
lsof -i :80
kill -9 <进程ID>

# 方案2:修改 .env 文件中的端口
APP_PORT=8081
FRONTEND_PORT=8080
DB_PORT=5433

陷阱 2:Docker 内存不足 🔴

现象

容器频繁重启,或卡在 "Starting" 状态

原因:Docker Desktop 默认内存限制太低(2GB)

解决方案

  1. 打开 Docker Desktop
  2. Settings → Resources → Advanced
  3. 将 Memory 调整到 至少 8GB(推荐 12GB)
  4. 点击 "Apply & Restart"

陷阱 3:网络问题导致镜像下载失败 🔴

现象

Error response from daemon: Get https://registry-1.docker.io/...

原因:国内访问 Docker Hub 可能很慢或失败

解决方案
配置国内镜像加速器(推荐阿里云):

  1. 打开 Docker Desktop
  2. Settings → Docker Engine
  3. 添加镜像加速器:
    {
         
      "registry-mirrors": [
        "https://docker.mirrors.ustc.edu.cn",
        "https://hub-mirror.c.163.com"
      ]
    }
    
  4. 点击 "Apply & Restart"

陷阱 4:向量维度不匹配 🟡

现象

ERROR: vector dimension mismatch

原因:Embedding 模型的向量维度与数据库配置不一致

解决方案

  1. 确认你使用的 Embedding 模型的维度(常见:384、768、1024)
  2. 如果不是 768 维,需要修改:
    # 重新初始化数据库
    make clean-db
    # 在初始化页面配置正确的向量维度
    

陷阱 5:Ollama 连接失败 🟡

现象

failed to connect to ollama: connection refused

原因:Ollama 未运行或连接地址配置错误

解决方案

# 方案1:安装并启动 Ollama
# 访问 https://ollama.com 下载安装
ollama serve

# 方案2:使用远程 API(如 OpenAI)
# 在初始化页面选择 "远程 API",填入 API 密钥

2. 循序渐进学习计划(四阶段法)

现在项目已经运行起来了,让我们开始有计划地深入学习!

阶段一:环境搭建和项目启动(1-2 天)⭐

目标:成功运行项目并能打个断点

学习任务

任务 1.1:完整体验核心功能(30分钟)

跟着我一步步操作:

  1. 注册并登录

    访问 http://localhost
    → 填写管理员账号信息
    → 登录进入系统
    
  2. 完成初始化配置

    → 配置 LLM 模型(推荐先用 Ollama + qwen2.5:7b)
    → 配置 Embedding 模型
    → (可选)配置 Rerank 模型
    
  3. 创建第一个知识库

    → 点击"创建知识库"
    → 命名为"测试知识库"
    → 上传一个简单的 TXT 文件(比如一篇文章)
    → 等待处理完成(状态变为"已完成")
    
  4. 进行第一次问答

    → 点击知识库的"对话"按钮
    → 提一个文档中相关的问题
    → 观察系统如何检索并回答
    

任务 1.2:理解 Docker 容器组成(1小时)

打开终端,执行以下命令并理解每个服务的作用:

# 查看所有运行中的容器
docker compose ps

# 查看各服务的日志
docker compose logs app           # Go 后端日志
docker compose logs docreader     # Python 文档处理服务日志
docker compose logs postgres      # 数据库日志

# 进入容器内部探索
docker exec -it WeKnora-app sh    # 进入 Go 后端容器
ls -la                            # 查看文件结构
exit                              # 退出容器

理解每个服务的角色

  • app:Go 后端,核心业务逻辑
  • frontend:Vue 前端,用户界面
  • postgres:数据库,存储知识、对话等数据
  • redis:缓存和任务队列
  • minio:对象存储,保存文档文件
  • docreader:Python 服务,解析各种格式的文档
  • jaeger:链路追踪,性能监控

任务 1.3:在 Go 代码中打断点调试(1-2小时)

这是学习的关键一步!

  1. 安装 VS Code + Go 扩展

  2. 停止 Docker 中的 app 服务

    docker compose stop app
    
  3. 本地运行 Go 后端

    # 安装依赖
    go mod download
    
    # 配置环境变量(复制 docker-compose.yml 中的 app 部分)
    export DB_HOST=localhost
    export DB_PORT=5432
    export DB_USER=weknora
    export DB_PASSWORD=your_password
    export DB_NAME=weknora
    # ... 其他环境变量
    
    # 运行
    cd cmd/server
    go run main.go
    
  4. 在关键位置打断点

    • internal/handler/session.goKnowledgeQA 方法
    • 在前端发起问答请求
    • 观察代码执行流程

验收标准

  • ✅ 能成功运行项目
  • ✅ 能完成一次完整的文档上传和问答流程
  • ✅ 理解各个容器的作用
  • ✅ 能在本地调试 Go 代码

阶段二:核心流程理解(3-5 天)⭐⭐

目标:追踪一个完整业务流程,画出自己的流程图

学习任务

任务 2.1:追踪"文档上传"完整流程(4-6小时)

步骤 1:从前端开始

打开 frontend/src/views/knowledge/index.vue,找到文档上传的代码:

// 找到上传文件的方法
const handleUpload = async (file) => {
   
  // 这里会调用 API
  const response = await uploadKnowledgeFile(knowledgeBaseId, file)
  // ...
}

步骤 2:跟踪 API 调用

打开 frontend/src/api/knowledge-base/index.ts,看 API 定义:

export const uploadKnowledgeFile = (kbId: string, file: File) => {
   
  return request.post(`/api/v1/knowledge-bases/${
     kbId}/knowledge/file`, formData)
}

步骤 3:后端路由

打开 internal/router/router.go,找到路由定义:

kb.POST("/file", handler.CreateKnowledgeFromFile)

步骤 4:Handler 处理

打开 internal/handler/knowledge.go,阅读 CreateKnowledgeFromFile 方法

步骤 5:Service 层业务逻辑

继续追踪到 Service 层,理解:

  • 文件如何保存到 MinIO
  • 如何调用 DocReader 解析
  • 如何分块
  • 如何向量化
  • 如何存储到数据库

练习:画出流程图

用你喜欢的工具(draw.io、Excalidraw 等)画出完整流程图,包括:

  • 前端 → 后端 → gRPC → 数据库 → 向量数据库
  • 标注每个步骤的关键函数名

任务 2.2:追踪"知识问答"完整流程(4-6小时)

重复类似的过程,但这次追踪问答流程:

  1. 找到前端发送问题的代码
  2. 找到后端的 KnowledgeQA handler
  3. 深入 chat_pipline.go,理解流水线编排
  4. 理解检索器如何工作(BM25 + 向量)
  5. 理解如何调用 LLM
  6. 理解流式响应如何实现

练习:修改提示词模板

  1. 打开 config/config.yaml
  2. 找到 conversation.summary.context_template
  3. 修改提示词,加入你的个性化内容
  4. 重启服务,观察效果变化

任务 2.3:使用 Jaeger 查看链路追踪(2小时)

  1. 访问 http://localhost:16686
  2. 在 Service 下拉框选择 "WeKnora"
  3. 点击 "Find Traces"
  4. 选择一条最近的 trace
  5. 观察完整的调用链路和耗时

分析性能瓶颈

  • 哪个步骤最慢?
  • 有没有并发执行的地方?
  • 数据库查询用了多长时间?

验收标准

  • ✅ 能画出文档上传和问答的完整流程图
  • ✅ 能找到任意功能对应的代码位置
  • ✅ 能通过 Jaeger 分析性能
  • ✅ 能独立修改提示词模板

阶段三:模块深入和定制开发(1-2 周)⭐⭐⭐

目标:能修改或扩展一个现有功能

学习任务

任务 3.1:实现一个新的检索器(难度:中等)

目标:集成 Weaviate 向量数据库

步骤

  1. 学习接口定义
    阅读 internal/types/interfaces/retriever.go

  2. 参考现有实现
    阅读 internal/application/repository/retriever/postgres/repository.go

  3. 实现新的 Retriever

    // internal/application/repository/retriever/weaviate/repository.go
    type WeaviateRetriever struct {
         
        client *weaviate.Client
    }
    
    func (r *WeaviateRetriever) Search(ctx context.Context, req *types.SearchRequest) ([]*types.SearchResult, error) {
         
        // 实现 Weaviate 检索逻辑
        // ...
    }
    
  4. 注册到工厂
    修改 internal/application/service/retriever/registry.go

  5. 测试
    编写单元测试并验证功能

任务 3.2:添加缓存层(难度:中等)

目标:对热门问题缓存答案,减少 LLM 调用

实现思路

  1. ChatPipeline 中,调用 LLM 前先查缓存
  2. 使用 Redis,key 为问题的 hash,value 为答案
  3. 设置合理的过期时间(如 1 小时)

代码位置internal/application/service/chat_pipline/chat_pipline.go

任务 3.3:实现新的文档格式支持(难度:较难)

目标:支持 Markdown 文件的解析

实现思路

  1. services/docreader/src/parsers/ 下新建 markdown_parser.py
  2. 实现解析逻辑(提取标题、内容、代码块等)
  3. 注册解析器到 grpc_server.py
  4. 测试上传 Markdown 文件

验收标准

  • ✅ 成功实现至少一个新功能
  • ✅ 代码通过 Code Review 标准
  • ✅ 编写了相应的测试用例
  • ✅ 更新了相关文档

阶段四:架构理解和贡献指南(2 周+)⭐⭐⭐⭐

目标:能理解技术选型原因,并尝试修复一个简单 issue

学习任务

任务 4.1:深入理解依赖注入容器(3-5天)

  1. 阅读 internal/container/container.gointernal/runtime/container.go
  2. 理解 uber/dig 的工作原理
  3. 尝试添加一个新的 Service 并注入

任务 4.2:理解 OpenTelemetry 实现(3-5天)

  1. 阅读 internal/tracing/init.go
  2. 学习如何在新的地方添加 Span
  3. 学习如何记录自定义属性

任务 4.3:贡献代码到开源项目(持续)

  1. 找到合适的 Issue

  2. Fork 项目并创建分支

    git clone https://github.com/你的用户名/WeKnora.git
    cd WeKnora
    git checkout -b feature/your-feature-name
    
  3. 实现功能并提交

    git add .
    git commit -m "feat: add your feature"
    git push origin feature/your-feature-name
    
  4. 创建 Pull Request

    • 在 GitHub 上创建 PR
    • 填写清晰的描述
    • 等待 Code Review

验收标准

  • ✅ 理解整体架构设计的权衡
  • ✅ 能解释为什么选择 Go 而不是 Python
  • ✅ 能解释依赖注入的好处
  • ✅ 成功提交至少一个 PR

3. 学习路径流程图

graph TD
    A[开始学习 WeKnora] --> B{你的基础如何?}

    B -->|完全新手| C[阶段一:环境搭建<br/>1-2天]
    B -->|有 Web 开发经验| D[阶段二:核心流程<br/>3-5天]
    B -->|后端开发老手| E[阶段三:模块深入<br/>1-2周]

    C --> F[✅ 成功运行项目<br/>✅ 完成第一次问答]
    F --> G{遇到问题?}
    G -->|是| H[查看常见陷阱部分<br/>或提Issue求助]
    G -->|否| D

    D --> I[✅ 画出流程图<br/>✅ 修改提示词]
    I --> J{想深入吗?}
    J -->|是| E
    J -->|先学基础| K[补充 Go/RAG 知识]
    K --> E

    E --> L[✅ 实现新功能<br/>✅ 通过测试]
    L --> M{想贡献代码?}
    M -->|是| N[阶段四:开源贡献<br/>2周+]
    M -->|暂时不| O[继续深入其他模块]

    N --> P[✅ 提交 PR<br/>✅ Code Review]
    P --> Q[🎉 成为 Contributor]
    O --> E

    style A fill:#e1f5ff
    style Q fill:#c8e6c9
    style F fill:#fff9c4
    style I fill:#fff9c4
    style L fill:#fff9c4
    style P fill:#fff9c4

第四部分:实践建议和进阶指导(从会用到精通)💡

1. 调试技巧和常见陷阱

🐛 调试技巧

技巧 1:善用日志

WeKnora 的日志非常详细,学会看日志能解决 80% 的问题:

# 实时查看所有服务日志
docker compose logs -f

# 只看特定服务
docker compose logs -f app

# 查看最近 100 行
docker compose logs --tail=100 app

# 搜索关键词
docker compose logs app | grep "error"

技巧 2:使用 Jaeger 定位性能问题

  1. 访问 http://localhost:16686
  2. 找到慢的请求(Duration 排序)
  3. 点击查看详细的 Span
  4. 找到耗时最长的操作

技巧 3:数据库调试

# 进入 PostgreSQL 容器
docker exec -it WeKnora-postgres psql -U weknora -d weknora

# 查看所有表
\dt

# 查看知识库
SELECT * FROM knowledge_bases LIMIT 10;

# 查看文档块
SELECT id, knowledge_id, content, embedding <=> '[0.1, 0.2, ...]'::vector AS distance
FROM chunks
ORDER BY distance
LIMIT 5;

# 退出
\q

技巧 4:gRPC 调试

使用 grpcurl 调试 DocReader 服务:

# 安装 grpcurl
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest

# 列出所有服务
grpcurl -plaintext localhost:50051 list

# 调用解析服务
grpcurl -plaintext -d '{"file_path": "/path/to/file.pdf"}' \
  localhost:50051 docreader.DocReaderService/ParseDocument

⚠️ 常见陷阱(Top 10)

根据社区反馈,这是最容易踩的10个坑:

  1. 忘记启动 Ollama
  2. 向量维度不匹配
  3. Redis 内存溢出(默认配置太小)
  4. 文件权限问题(volumes 挂载)
  5. 网络问题(容器间通信)
  6. 配置文件未更新(修改后忘记重启)
  7. 端口冲突
  8. Docker 内存不足
  9. 数据库连接数耗尽
  10. 提示词模板格式错误

详细解决方案请参见"阶段一"的"环境配置陷阱"部分。


2. 扩展练习建议

🌱 入门级练习

  1. 修改欢迎消息

    • 位置:config/config.yaml
    • 修改默认的回答模板
    • 难度:⭐
  2. 调整检索参数

    • 修改 embedding_top_krerank_top_k
    • 观察对结果的影响
    • 难度:⭐
  3. 添加新的 API 接口

    • 实现一个"统计知识库数量"的接口
    • 涉及:Router → Handler → Service → Repository
    • 难度:⭐⭐

🌿 中级练习

  1. 实现答案评价功能

    • 前端添加"👍/👎"按钮
    • 后端记录评价到数据库
    • 用于后续优化
    • 难度:⭐⭐⭐
  2. 集成新的 Embedding 模型

    • 比如使用 text2vec-large-chinese
    • 实现 EmbeddingModel 接口
    • 难度:⭐⭐⭐
  3. 实现多轮对话摘要

    • 当对话超过 10 轮时,自动摘要前面的内容
    • 减少上下文长度
    • 难度:⭐⭐⭐

🌳 高级练习

  1. 实现分布式部署

    • 将各服务拆分到不同机器
    • 配置服务发现
    • 难度:⭐⭐⭐⭐
  2. 性能优化挑战

    • 目标:将问答响应时间从 3 秒降到 1 秒
    • 思路:缓存、并发、索引优化
    • 难度:⭐⭐⭐⭐⭐
  3. 实现知识图谱可视化

    • 前端使用 D3.js 或 ECharts
    • 展示实体和关系
    • 支持交互式探索
    • 难度:⭐⭐⭐⭐⭐

3. 参与贡献的途径

🤝 如何成为 Contributor

步骤 1:了解项目规范

阅读以下文档:

  • README_CN.md - 项目介绍
  • CONTRIBUTING.md - 贡献指南(如果有)
  • Code of Conduct - 行为准则

步骤 2:找到合适的 Issue

在 GitHub Issues 页面筛选:

  • 标签:good first issuehelp wanted
  • 难度:选择适合自己水平的
  • 兴趣:选择你感兴趣的方向

步骤 3:认领 Issue

在 Issue 下评论:

Hi, I'd like to work on this issue. Could you assign it to me?

等待维护者回复确认。

步骤 4:开发和测试

# Fork 并克隆
git clone https://github.com/你的用户名/WeKnora.git
cd WeKnora

# 创建功能分支
git checkout -b feature/issue-123-add-new-feature

# 开发...
# 编写测试...

# 提交
git add .
git commit -m "feat: add new feature for #123"
git push origin feature/issue-123-add-new-feature

步骤 5:创建 Pull Request

在 GitHub 上创建 PR,标题格式:

feat: add new feature (#123)

描述模板:

## 变更说明
简要描述你做了什么改动

## 相关 Issue
Closes #123

## 测试
- [x] 添加了单元测试
- [x] 本地测试通过
- [x] 更新了文档

## 截图(如适用)
贴上前后对比图

步骤 6:Code Review

  • 耐心等待 Review
  • 根据反馈修改代码
  • 保持礼貌和专业

步骤 7:合并和庆祝 🎉

当 PR 被合并后,你就成为了 WeKnora 的 Contributor!


第五部分:技术栈学习指引(你的知识地图)🌐

1. 官方文档定位(学习的基石)

核心技术栈文档

技术 官方文档 重点章节 学习时长
Go 语言 go.dev/doc Tour of Go、Effective Go 1-2 周
Gin 框架 gin-gonic.com/docs Quickstart、Middleware 2-3 天
GORM gorm.io/zh_CN CRUD、关联查询 3-5 天
PostgreSQL postgresql.org/docs SQL 语法、索引、性能调优 1 周
pgvector GitHub 安装、使用、性能 1-2 天
Redis redis.io/docs 数据类型、持久化 3-5 天
Docker docs.docker.com 容器基础、Compose 3-5 天
Vue 3 vuejs.org Composition API、Router 1 周
OpenTelemetry opentelemetry.io/docs 链路追踪基础 2-3 天

项目自身文档

文档 位置 内容 优先级
README README_CN.md 项目介绍、快速开始 ⭐⭐⭐⭐⭐
API 文档 docs/API.md 接口说明 ⭐⭐⭐⭐
问题排查 docs/QA.md 常见问题 ⭐⭐⭐⭐
详细设计 docs/WeKnora.md 架构设计文档 ⭐⭐⭐
数据库结构 migrations/paradedb/ 数据库 Schema ⭐⭐⭐

权威技术书籍

Go 语言

  1. 《Go 程序设计语言》- 官方推荐
  2. 《Go 语言高级编程》- 深入并发和接口
  3. 《Effective Go》- 官方最佳实践(免费)

系统设计

  1. 《设计数据密集型应用》- 分布式系统必读
  2. 《微服务架构设计模式》
  3. 《领域驱动设计》

AI/ML

  1. 《动手学深度学习》- 理解 Embedding
  2. 《自然语言处理综论》
  3. 《大规模语言模型》

2. 学习路径建议(社区智慧)

技能学习顺序

graph LR
    A[Go 基础语法] --> B[Gin Web 框架]
    B --> C[GORM 数据库操作]
    C --> D[Docker 容器化]
    D --> E[RAG 原理]
    E --> F[向量检索]
    F --> G[LLM 集成]
    G --> H[分布式追踪]

    style A fill:#ffcdd2
    style E fill:#c8e6c9
    style H fill:#bbdefb

核心概念优先级

必须掌握 ⭐⭐⭐⭐⭐:

  • Go 并发编程(goroutine、channel)
  • RESTful API 设计
  • SQL 和数据库索引
  • Docker 基本使用
  • RAG 基本原理

重要 ⭐⭐⭐⭐:

  • SOLID 原则
  • 依赖注入
  • 向量检索算法
  • LLM API 调用
  • 链路追踪

进阶 ⭐⭐⭐:

  • 设计模式
  • 性能调优
  • 分布式系统
  • OpenTelemetry 深度使用

实践项目推荐

在学习 WeKnora 的同时,可以参考这些项目:

  1. Dify(Python):另一个知名的 LLM 应用框架
  2. FastGPT(TypeScript):类似的知识库问答系统
  3. Langchain-Go:Go 版本的 LangChain
  4. Milvus:专业的向量数据库

3. 工具与环境配置指南

开发环境搭建

推荐配置

工具 推荐版本 用途
IDE VS Code 或 GoLand 代码编辑
Go 1.24+ 后端开发
Node.js 18+ 前端开发
Docker Desktop 最新版 容器管理
Git 2.30+ 版本控制
Postman 最新版 API 测试

VS Code 必装扩展

  • Go(官方)
  • Docker
  • GitLens
  • REST Client
  • Database Client
  • Mermaid Preview

GoLand 配置

  • 启用 Go Modules
  • 配置远程调试
  • 安装 Database Tools

常用工具使用

Postman 测试 API

  1. 导入 API 集合(如果有)
  2. 配置环境变量:

    {
         
      "base_url": "http://localhost:8080",
      "token": "your_jwt_token"
    }
    
  3. 测试登录:

    POST {
        {base_url}}/api/v1/auth/login
    Body: {
      "username": "admin",
      "password": "password"
    }
    

Git 工作流

# 拉取最新代码
git pull origin main

# 创建功能分支
git checkout -b feature/my-feature

# 提交代码(遵循 Conventional Commits)
git commit -m "feat: add new feature"
git commit -m "fix: resolve bug #123"
git commit -m "docs: update README"

# 推送到远程
git push origin feature/my-feature

4. 进阶拓展方向

技术博客与专家观点

推荐关注的技术博客

  1. Go 语言相关

    • Go 官方博客:blog.golang.org
    • Dave Cheney 的博客:dave.cheney.net
    • Go 语言中文网:studygolang.com
  2. RAG 和 LLM

    • LangChain Blog
    • OpenAI Cookbook
    • Hugging Face Blog
  3. 系统设计

    • Martin Fowler 的博客
    • High Scalability Blog

相关技术大会

  • GopherCon:Go 语言年度盛会
  • KubeCon:云原生技术
  • AI 大会:关注 LLM 和 RAG 技术进展

社区与论坛

平台 链接 适用场景
GitHub Discussions WeKnora 项目页 项目相关讨论
Go 语言中文网 studygolang.com Go 语言学习
V2EX v2ex.com 技术讨论
知乎 搜索相关话题 经验分享
Stack Overflow stackoverflow.com 技术问答

结语 🎓

恭喜你看到这里!这份指南凝聚了我对 WeKnora 项目的深入分析和学习路径设计。

记住几个关键点

  1. 不要试图一次性掌握所有内容。按照四阶段学习路径,循序渐进。
  2. 实践是最好的老师。多动手,多调试,多尝试。
  3. 遇到问题不要怕。查文档、看日志、问社区,总能解决。
  4. 保持好奇心。思考"为什么这样设计",而不是只看"怎么用"。
  5. 分享你的收获。写博客、提 PR、帮助他人,这也是学习的一部分。

下一步行动建议

✅ 立即行动:按照"阶段一"的指南,今天就把项目跑起来
✅ 设定目标:选择一个你感兴趣的方向深入学习
✅ 加入社区:在 GitHub Discussions 上介绍自己
✅ 分享进展:记录学习笔记,帮助后来者

祝你学习愉快,早日成为 WeKnora 的 Contributor!💪

目录
相关文章
|
11天前
|
存储 关系型数据库 分布式数据库
PostgreSQL 18 发布,快来 PolarDB 尝鲜!
PostgreSQL 18 发布,PolarDB for PostgreSQL 全面兼容。新版本支持异步I/O、UUIDv7、虚拟生成列、逻辑复制增强及OAuth认证,显著提升性能与安全。PolarDB-PG 18 支持存算分离架构,融合海量弹性存储与极致计算性能,搭配丰富插件生态,为企业提供高效、稳定、灵活的云数据库解决方案,助力企业数字化转型如虎添翼!
|
9天前
|
存储 人工智能 搜索推荐
终身学习型智能体
当前人工智能前沿研究的一个重要方向:构建能够自主学习、调用工具、积累经验的小型智能体(Agent)。 我们可以称这种系统为“终身学习型智能体”或“自适应认知代理”。它的设计理念就是: 不靠庞大的内置知识取胜,而是依靠高效的推理能力 + 动态获取知识的能力 + 经验积累机制。
349 130
|
9天前
|
存储 人工智能 Java
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
本文讲解 Prompt 基本概念与 10 个优化技巧,结合学术分析 AI 应用的需求分析、设计方案,介绍 Spring AI 中 ChatClient 及 Advisors 的使用。
440 130
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
|
3天前
|
存储 安全 前端开发
如何将加密和解密函数应用到实际项目中?
如何将加密和解密函数应用到实际项目中?
205 138
|
10天前
|
人工智能 Java API
AI 超级智能体全栈项目阶段一:AI大模型概述、选型、项目初始化以及基于阿里云灵积模型 Qwen-Plus实现模型接入四种方式(SDK/HTTP/SpringAI/langchain4j)
本文介绍AI大模型的核心概念、分类及开发者学习路径,重点讲解如何选择与接入大模型。项目基于Spring Boot,使用阿里云灵积模型(Qwen-Plus),对比SDK、HTTP、Spring AI和LangChain4j四种接入方式,助力开发者高效构建AI应用。
396 122
AI 超级智能体全栈项目阶段一:AI大模型概述、选型、项目初始化以及基于阿里云灵积模型 Qwen-Plus实现模型接入四种方式(SDK/HTTP/SpringAI/langchain4j)
|
3天前
|
存储 JSON 安全
加密和解密函数的具体实现代码
加密和解密函数的具体实现代码
202 136
|
22天前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1361 8
|
8天前
|
监控 JavaScript Java
基于大模型技术的反欺诈知识问答系统
随着互联网与金融科技发展,网络欺诈频发,构建高效反欺诈平台成为迫切需求。本文基于Java、Vue.js、Spring Boot与MySQL技术,设计实现集欺诈识别、宣传教育、用户互动于一体的反欺诈系统,提升公众防范意识,助力企业合规与用户权益保护。