【踩坑复盘】我在本地跑 RAG 知识库时踩了 5 个大坑,吐血整理避坑指南

前言

大家好,我是去年开始研究 RAG 的后端开发。

本地跑通一个 RAG 知识库听着简单------不就是"文档切分 → 向量化 → 检索 → LLM 生成"吗?但真正动手时,各种奇奇怪怪的坑一个接一个。

花了 2 周踩坑,终于把系统跑通了。 这篇文章把我踩过的 5 个大坑整理出来,避免大家再走弯路。


坑 1:LM Studio API Token 被坑了一整天 🔥

调用 http://localhost:1234/api/v1/chat 时,开始完全不报错------能正常返回。后来突然开始报:

css 复制代码
An LM Studio API token is required to make requests to this server,
but none was provided using the Authorization header

我以为 Token 过期了,重启 LM Studio、重新生成 Token,还是一样。

最后发现:LM Studio 有两套 API!

API 类型 端点 Token
Local Server API /v1/chat/completions ✅ 需要 Bearer Token
Developer API /api/v1/chat 部分版本免 Token
java 复制代码
// ✅ 正确:Local Server API + Bearer Token
String url = lmstudioUrl + "/v1/chat/completions";

Request request = new Request.Builder()
    .url(url)
    .addHeader("Authorization", "Bearer " + apiKey)  // 关键!
    .addHeader("Content-Type", "application/json")
    .post(RequestBody.create(jsonBody, MediaType.parse("application/json")))
    .build();

// ❌ 错误:Developer API 免 Token 的写法,不通用
String url = lmstudioUrl + "/api/v1/chat";

关键点:看清楚你调的是哪套 API,Token 策略完全不同!


坑 2:Embedding 向量维度不匹配,Qdrant 存储报错 🔥

向量化存储时报错:

vbnet 复制代码
Response: BadRequest:{"status":{"error":"Wrong vector dimension...

我的 Embedding 模型是 text-embedding-bge-base-zh-v1.5,理论上输出 768 维向量。但 Qdrant 创建 Collection 时,我用了默认维度 1024。

先测一次向量维度:

json 复制代码
curl http://localhost:1234/v1/embeddings \
  -H "Authorization: Bearer $LM_API_TOKEN" \
  -d '{"model":"text-embedding-bge-base-zh-v1.5","input":["测试文本"]}'

返回结果里数组长度就是真实维度。

创建 Qdrant Collection 时指定正确维度:

scss 复制代码
// ✅ 正确
qdrantClient.createCollection(
    CollectionName,
    VectorParams.builder()
        .size(768)  // 和 Embedding 模型输出维度一致!
        .distance(Distance.Cosine)
        .build()
);

// ❌ 错误:用错了维度
.size(1024)  // 导致存储失败

避坑建议: 把向量维度写成配置项:

yaml 复制代码
# application.yml
qdrant:
  vector-dimension: 768

坑 3:文本切分把句子拦腰截断,回答质量断崖式下降 🔥

早期用的是纯长度切分:

arduino 复制代码
// ❌ 简单粗暴的切分------把句子拦腰截断
String chunk = text.substring(i, i + 1000);

结果:检索出来的片段经常是半截句子,LLM 完全无法理解。

比如切到"公司成立于 201"------LLM 根本不知道后面是什么。

scss 复制代码
public List<String> chunkText(String text) {
    List<String> chunks = new ArrayList<>();
    StringBuilder current = new StringBuilder();

    // ✅ 按句子边界分割(中文:。!?;\n)
    String[] sentences = text.split("(?<=[。!?.!?;;\n])");

    for (String sentence : sentences) {
        // 当前块加上这句超过阈值
        if (current.length() + sentence.length() > chunkSize) {
            // 保存当前块
            if (current.length() > 0) {
                chunks.add(current.toString().trim());
            }

            // 保留重叠部分(避免丢失上下文)
            int overlapLen = Math.min(chunkOverlap, current.length());
            current = new StringBuilder(
                    current.toString().substring(current.length() - overlapLen)
            );
        }
        current.append(sentence);
    }

    if (current.length() > 0) {
        chunks.add(current.toString().trim());
    }
    return chunks;
}

加上重叠(Overlap)效果更好:

ini 复制代码
Chunk1: [句子1][句子2][句子3]...
Chunk2: [...句子3][句子4][句子5]...  ← 重叠部分保证上下文连续

坑 4:LM Studio Embedding 接口不稳定(/v1/embeddings) 🔥

部分版本的 LM Studio,/v1/embeddings 接口返回错误:

json 复制代码
{"error": "model not found"}

但明明 v1/models 里能看到这个模型。

原因

LM Studio 对 Embedding 模型的支持比较微妙,有些 GGUF 格式的 Embedding 模型在部分版本中不稳定。

解决方案

换成 Ollama 运行 Embedding

bash 复制代码
# 安装 Ollama
winget install Ollama.Ollama

# 下载 Embedding 模型(nomic-embed-text,约 274MB)
ollama pull nomic-embed-text

# 启动
ollama serve

修改配置:

yaml 复制代码
# application.yml
ollama:
  base-url: http://localhost:1234  # 如果 LM Studio 在这里
  embeddings-model: nomic-embed-text

# 改成 Ollama:
ollama:
  base-url: http://localhost:11434
  embeddings-model: nomic-embed-text

坑 5:向量检索相似度阈值设错,噪声答案满天飞 🔥

系统上线后,经常出现"答非所问"的情况------检索出来的片段和用户问题根本不相关,但 LLM 硬是"强行回答"了。

看了日志,发现检索出来的片段相似度只有 0.1~0.2(理论上 0.5+ 才算相关),但都被塞进 Prompt 里了。

scss 复制代码
public List<SearchResult> search(String query, int topK) {
    List<SearchResult> allResults = qdrantClient.search(...);

    // ✅ 加阈值过滤:只返回相似度 >= 0.3 的结果
    return allResults.stream()
            .filter(r -> r.getScore() >= 0.3)
            .limit(topK)
            .collect(Collectors.toList());
}

不同 Embedding 模型相似度分布不同,建议先跑几个测试:

Embedding 模型 优质答案阈值
bge-base-zh-v1.5 ≥ 0.5
nomic-embed-text ≥ 0.6
text-embedding-v2 ≥ 0.55

总结一下: 5 个坑一次排雷

原因 解决
LM Studio Token 不一致 两套 API 混用 统一用 Local Server API + Bearer Token
向量维度不匹配 Qdrant 维度写错 先测试实际维度再创建 Collection
文本切分截断句子 纯长度切分 按句子边界切分 + 重叠
Embedding 接口不稳定 LM Studio 版本问题 换成 Ollama 或在线 API
噪声答案满天飞 无阈值过滤 score >= threshold 过滤

相关推荐
颜酱几秒前
06 | 把 meta_config 同步进 MySQL(生成阶段)
前端·人工智能·后端
stereohomology14 分钟前
实战微调排版细节:豆包Seed 2.1 Turbo 不弱于GLM5.2?
人工智能·大模型·对比·why不coding
renhongxia134 分钟前
世界模型的四个商业场景:自动驾驶、机器人、内容产业与工业仿真
人工智能·机器人·自动驾驶
stormzhangV1 小时前
AI 的玩法,该做减法了
人工智能·ai编程·claude
IT_陈寒1 小时前
SpringBoot自动配置坑了我一周,原来问题这么蠢!
前端·人工智能·后端
糯米导航1 小时前
实践教程|搭建电商 AI 无限画布,实现百款商品主图自动化批量生成
运维·人工智能·自动化
朴马丁2 小时前
从制造到智造:PLM如何赋能企业研发创新
大数据·运维·人工智能·食品行业·流程行业plm·化工新材料行业·新能源材料行业
武子康2 小时前
GAIA、Cosmos、Genie 等视频模型纷纷自称"世界模型",为什么说视觉逼真度不构成决策证据?
人工智能·llm·agent
上海锝秉工控2 小时前
普通编码器:基础信号处理与数据转换核心岗
人工智能·信号处理
chenyuhao20242 小时前
第一章_自动驾驶中的社会交互
人工智能·机器学习·自动驾驶