Skip to content
🔗 分享本题
查看我的学习进度 →

项目经验模块 Q1 教学图:完整讲述 RAG 系统项目

🧠 图解记忆:用基线、关键取舍和量化结果证明 RAG 项目价值;点击图片可查看原图。

💡 STAR回答模板

S (Situation - 背景):

"我在xx公司负责开发一个企业级知识库问答系统,主要服务内部员工查询公司文档、政策、技术文档等。知识库包含5000+文档,总计200万字,涵盖HR、技术、产品等多个领域。"

T (Task - 任务):

"项目目标是实现:

  1. 准确率>85% (用户满意度)
  2. 平均响应时间<2秒
  3. 成本可控(月<$500)
  4. 支持中英文混合查询"

A (Action - 行动):

1. 技术架构设计

python
# 技术栈选择
向量数据库: Qdrant (开源,支持混合检索)
Embedding模型: bge-large-zh-v1.5 (中文效果好)
LLM: DeepSeek-V4-Flash (成本平衡)
框架: LangChain

# 核心流程
用户提问 → Query改写(补充上下文)
         → 混合检索(BM25 + 语义)
         → Rerank精排(BGE-Reranker)
         → 上下文压缩(LLMLingua)
         → LLM生成答案
         → 引用来源标注

2. 关键优化点

(1) 分块策略优化

python
# 问题: 固定512 token分块效果差
# 原因: 切断了语义完整性

# 解决: 语义分块 + 重叠
from langchain.text_splitter import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=800,           # 略大,保留更多上下文
    chunk_overlap=200,        # 20%重叠,避免边界问题
    separators=["\n\n", "\n", "。", ".", " "],  # 优先按段落
)

# 效果: 召回率 68% → 79%

(2) 混合检索实现

python
def hybrid_search(query, top_k=20):
    # BM25检索
    bm25_results = bm25_retriever.search(query, k=top_k)

    # 向量检索
    vector_results = vector_db.search(
        embedding_model.encode(query),
        k=top_k
    )

    # RRF融合
    final_results = reciprocal_rank_fusion(
        [bm25_results, vector_results],
        k=60
    )

    return final_results[:10]  # 取top-10

# 效果: 召回率 79% → 87%

(3) Rerank精排

python
from sentence_transformers import CrossEncoder

reranker = CrossEncoder('BAAI/bge-reranker-large')

def rerank(query, candidates):
    # 计算query与每个candidate的相关性分数
    scores = reranker.predict([
        [query, doc.content] for doc in candidates
    ])

    # 按分数排序
    ranked = sorted(
        zip(candidates, scores),
        key=lambda x: x[1],
        reverse=True
    )

    return [doc for doc, _ in ranked[:5]]

# 效果: 精确率 73% → 89%

(4) 成本优化 - 语义缓存

python
from langchain.cache import RedisSemanticCache

# 相似问题直接返回缓存答案
cache = RedisSemanticCache(
    redis_url="redis://localhost:6379",
    embedding=embedding_model,
    score_threshold=0.85  # 相似度>0.85命中缓存
)

# 缓存命中率: 35%
# 成本节省: 35% API调用

R (Result - 结果):

"项目上线后:

  • 准确率达到89% (超过目标85%)
  • P95响应时间1.8秒 (目标<2秒)
  • 月成本**$320** (节省36%,目标$500)
  • 日均处理**2000+**次查询
  • 用户满意度4.3/5

核心突破点:

  1. 混合检索+Rerank,召回率提升19%
  2. 语义缓存,成本降低35%
  3. 语义分块,召回率提升11%"

面试追问应对:

Q: "为什么选择Qdrant而不是Pinecone/Milvus?"

"我们对比了3个方案:

  • Pinecone: 云服务,易用但贵($70/月起)
  • Milvus: 功能强大但部署复杂,需要K8s
  • Qdrant: 开源免费,Docker部署简单,支持混合检索⭐

我们团队规模小,选Qdrant自部署,成本$0,功能够用。"

Q: "遇到的最大难点是什么?怎么解决的?"

"最大难点是长文档检索不准

问题现象:

  • 用户问'请假流程',检索到的chunk是'考勤制度第3章',但答案在第5章
  • 召回率只有68%

分析原因:

  • 固定512 token分块,切断了语义
  • 标题和正文分离,丢失了上下文

解决方案:

  1. 语义分块: 按段落/标题层级切分
  2. 增加chunk_overlap: 200 token重叠
  3. Parent-Child索引: 检索时返回父chunk

效果: 召回率68%→79%,提升11%"

Q: "如果让你重新设计,会怎么改进?"

"3个改进方向:

  1. 引入HyDE (假设性文档嵌入)

    • 当前: 直接用用户问题检索
    • 改进: 先让LLM生成假设答案,用假设答案检索
    • 预期: 召回率+5%
  2. 多路召回+学习排序

    • 当前: BM25 + Vector 两路
    • 改进: + 时间相关性 + 用户历史偏好
    • 预期: 个性化提升
  3. Fine-tune Embedding模型

    • 当前: 通用bge模型
    • 改进: 在企业文档上微调
    • 预期: 领域适配性+10%"

📚 参考:STAR 法则(Wikipedia:Situation, Task, Action, Result)