# rag2 **Repository Path**: jssbzg/rag2 ## Basic Information - **Project Name**: rag2 - **Description**: No description available - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-01-21 - **Last Updated**: 2026-01-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # RAG智能问答系统 基于Spring Boot和LangChain4j的检索增强生成(RAG)应用,支持文档上传、向量化存储和智能问答。 ## 技术栈 - **后端**: Spring Boot 3.2.5 + JDK 17 - **AI框架**: LangChain4j 0.36.0 - **向量存储**: PostgreSQL + pgvector - **AI接口**: OpenAI兼容API(支持NVIDIA NIM) - **前端**: HTML/CSS/JavaScript ## 快速开始 ### 1. 环境准备 **PostgreSQL + pgvector** ```sql -- 创建数据库 CREATE DATABASE ragdb; -- 连接到ragdb后启用pgvector扩展 CREATE EXTENSION vector; ``` **配置API密钥** 编辑 `application.yml` 或设置环境变量: ```bash set LLM_API_KEY=your-openai-api-key ``` 如果使用NVIDIA NIM: ```bash set LLM_API_KEY=nvapi-your-nvidia-api-key set LLM_API_URL=https://integrate.api.nvidia.com/v1 set EMBEDDING_API_URL=https://integrate.api.nvidia.com/v1 ``` ### 2. 运行应用 ```powershell # 进入项目目录 cd c:\Users\aaron\Desktop\rag2 # 编译运行 .\mvnw.cmd spring-boot:run ``` ### 3. 访问应用 打开浏览器访问: http://localhost:10443 ## API接口 ### 对话接口 **流式对话 (SSE)** ``` GET /api/chat/stream?question=你的问题&useRag=true ``` **普通对话** ``` POST /api/chat Content-Type: application/json { "question": "你的问题", "useRag": true } ``` ### 文档接口 ``` POST /api/documents/upload - 上传文档 GET /api/documents - 获取文档列表 DELETE /api/documents/{id} - 删除文档 GET /api/documents/stats - 获取统计信息 ``` ## 参数配置详解与调优指南 (Configuration & Tuning) 以下参数位于 `src/main/resources/application.yml` 中,对 RAG 效果至关重要。 ### 1. LangChain4j 配置 (`langchain4j.open-ai`) #### 1.1 聊天模型配置 (`chat-model`) | 参数 | 说明 | 调优建议 | |------|------|----------| | `base-url` | 大模型 API 地址 | 默认使用 NVIDIA NIM,可替换为 OpenAI 或其他兼容端点 | | `api-key` | API 密钥 | 从对应平台获取 | | `model-name` | 模型名称 | **推荐**: `meta/llama-3.1-70b-instruct`, `gpt-4o` 等强推理模型。
**思路**: RAG 极其依赖模型的"阅读理解"能力。如果模型不够强,即使检索到了正确文档,它也可能回答错误或产生幻觉。 | | `max-tokens` | 最大回复长度 | 默认 `4096`。如果你的场景需要生成长文章,调大此值;如果是简短问答,调小以节省成本。 | | `temperature` | 温度 (创意度) | 范围 `0.0 - 1.0`。
**RAG 推荐值**: `0.0 - 0.3` (低确信度)。
**原因**: RAG 需要模型严格基于上下文回答,不需要模型"自由发挥"或展现创意,低温度能减少幻觉。 | #### 1.2 流式聊天模型配置 (`streaming-chat-model`) 配置与 `chat-model` 相同,用于支持流式输出。LangChain4j 会自动创建两个独立的 Bean。 #### 1.3 向量嵌入配置 (`embedding-model`) | 参数 | 说明 | 调优建议 | |------|------|----------| | `base-url` | Embedding API 地址 | 默认使用 NVIDIA NIM | | `api-key` | API 密钥 | 与聊天模型可使用相同密钥 | | `model-name` | Embedding 模型 | **推荐**: `nvidia/nv-embed-v1`, `text-embedding-3-large`。
**影响**: 决定了"语义搜索"的准确性。模型越强,越能理解"苹果"和"水果"的相关性。向量维度由模型自动决定(如 1024, 1536, 4096)。 | ### 2. 检索策略配置 (`rag.retrieval`) | 参数 | 说明 | 调优建议 | |------|------|----------| | `top-k` | 检索片段数量 | 默认 `5`。
**调大 (如 10)**: 能给 LLM 提供更多上下文,但也引入更多噪音(无关信息),且消耗更多 Token 费用。
**调小 (如 3)**: 上下文更精确,但可能漏掉关键信息。
**策略**: 如果上下文窗口很大 (如 128k),可以适当调大 `top-k`。 | | `similarity-threshold` | 相似度阈值 | 范围 `0.0 - 1.0`。默认 `0.3`。
**作用**: 过滤掉相关性极低的文档。
**调优**: 如果发现系统经常回答"找不到相关信息",可适当降低 (如 0.2);如果经常引用完全不相关的文档胡说八道,则提高 (如 0.5)。 | ### 3. 切片策略配置 (`rag.chunk`) | 参数 | 说明 | 调优建议 | |------|------|----------| | `size` | 切片大小 (字符) | 默认 `500`。
**过大**: 包含过多杂乱信息,稀释了关键语义,导致检索不准。
**过小**: 句子被切断,语义不完整。
**经验值**: 300-500 适合大多数文档;如果是代码或法律文书,可能需要更大。 | | `overlap` | 重叠大小 (字符) | 默认 `50`。
**作用**: 防止关键句子刚好切在两个片段中间,导致哪边都不完整。
**建议**: 一般设为 `size` 的 10%-20%。 | ## RAG 技术详解 (Retrieval-Augmented Generation) 本项目基于 LangChain4j 实现了标准的 RAG 流程,核心逻辑在于**让 LLM 具备查阅私有知识库的能力**。 ### 1. 数据处理流程 (Data Pipeline) 数据从上传到被检索使用的全过程: 1. **上传 (Upload)**: 用户上传 PDF/Markdown/TXT 文档。 2. **清洗与切分 (Text Splitting)**: * 将长文档切分为较短的片段 (Chunk),例如每 500 字符一段。 * **关键点**: 使用滑动窗口 (Overlap 50 chars) 保持相邻片段的上下文连贯,避免句子在中间被截断。 3. **向量化 (Embedding)**: * 使用 LangChain4j 的 `EmbeddingModel` 将每个文本片段转化为高维向量 (例如 4096 维)。 * *原理*: 语义相近的文本,其向量在空间中的距离更近。 4. **存储 (Indexing)**: * 将文本内容与对应的向量一同存储在 PostgreSQL (pgvector) 中。 ### 2. 问答流程 (Inference Pipeline) 当用户提问时: 1. **问题向量化**: 使用 LangChain4j 的 `EmbeddingModel` 将用户的自然语言问题转化为向量。 2. **语义检索 (Retrieval)**: * 使用余弦相似度 (Cosine Similarity) 在数据库中查找与问题向量最接近的 K 个文档片段。 * 相比传统的关键词搜索 (Keyword Search),它可以理解语义(例如"苹果"与"水果"及"科技公司"的关联)。 3. **构建提示词 (Prompt Engineering)**: * 将检索到的片段组装成 `Context` (上下文)。 * 模板: `"请基于以下上下文回答问题: [Context] 问题: [Question]"` 4. **生成回答 (Generation)**: * 使用 LangChain4j 的 `ChatLanguageModel` 阅读上下文并生成最终答案。 * 支持流式输出,实现打字机效果。 --- ## 商用优化指南 (Optimization for Production) 如果将本项目用于商业产品,建议从以下几个维度进行优化: ### 1. 数据质量与检索优化 (Data Quality & Retrieval) * **LangChain4j DocumentSplitters**: * 使用 LangChain4j 的 `DocumentSplitters.recursive()` 方法实现文档切分 * 支持基于字符的递归切分,按段落、句子、词的优先级进行分割 * 自动处理重叠,保持上下文连贯性 * **高级切分 (Advanced Chunking)**: * 不要只按字符切分。针对结构化文档(如 Markdown/HTML),应按标题、段落结构递归切分 (Recursive Character Splitter)。 * 当前实现使用 LangChain4j 的递归切分器,支持按段落、句子、字符的多级切分策略,保持语义完整性。 * **混合检索 (Hybrid Search)**: * 纯向量检索对专有名词(如产品型号 "X-2000")匹配效果不佳。 * **方案**: 结合 **向量检索 (Semantic)** + **关键词检索 (BM25/Elasticsearch)**,加权得出结果。 * **重排序 (Reranking)**: * 向量检索召回 Top-50 个片段,然后使用 Cross-Encoder 模型(如 BGE-Reranker)进行精细重排序,取 Top-5 给 LLM,显著提升准确率。 ### 2. 性能优化 (Performance) * **异步处理**: 文档上传后的向量化过程较慢,应改为消息队列 (RabbitMQ/Kafka) 异步处理,前端显示处理进度。 * **向量库索引**: 数据量超过 10 万时,必须建立 IVFFlat 或 HNSW 索引,否则全表扫描速度会很慢。 * **缓存 (Caching)**: * 高频问题的 Embedding 结果可以缓存 (Redis)。 * LangChain4j 提供了 `ChatMemory` 组件,可以缓存对话历史。 ### 3. 应用层优化 (Application) * **多轮对话 (Multi-turn Conversation)**: * 当前仅支持单轮问答。商用需维护会话历史,将"它是什么"中的"它"指代消解后再检索。 * LangChain4j 的 `ChatMemory` 可以轻松实现多轮对话。 * **意图识别 (Router)**: * 在检索前增加意图分类层:由于"你好"这类闲聊不需要检索知识库,直接回答即可,节省 Token 成本。 * **引用溯源**: 在 UI 上高亮显示答案引用的原文段落,增加可信度。 ### 4. 评估体系 (Evaluation) * 建立自动化测试集,使用 **RAGAS** 或 **TruLens** 框架评估: * **Context Precision**: 检索到的上下文是否包含正确答案? * **Answer Faithfulness**: 回答是否忠实于上下文(有无幻觉)? ## 常见问题排查 (Troubleshooting) ### Q: 为什么有时候提问无法命中(检索到)文档? 如果你发现提问后系统回答"我不知道"或者没有利用上传的文档回答,通常有以下几个原因: 1. **相似度阈值 (Similarity Threshold) 过高** * **现象**: 后台日志显示检索到了片段,但在 Java 代码过滤时通过 `filter(chunk -> chunk.getSimilarity() >= similarityThreshold)` 被剔除了。 * **解决**: 在 `application.yml` 中降低 `rag.retrieval.similarity-threshold`,例如从 `0.3` 降到 `0.2` 甚至 `0.1` 试试。 2. **Top-K 设置过小** * **现象**: 正确答案在相关性排名的第 6 或 7 位,但 `top-k` 只取了前 5。 * **解决**: 增大 `rag.retrieval.top-k` 到 8 或 10。 3. **切片 (Chunking) 问题** * **现象**: 问题的答案跨越了两个切片,导致任何一个单独切片的语义都不足以匹配问题。 * **解决**: 增大 `rag.chunk.overlap` (重叠区),或者增大 `rag.chunk.size`。 4. **Embedding 模型语义理解差异** * **现象**: 即使关键词匹配,但向量距离依然很远。例如文档写"苹果公司",提问"iPhone制造商",某些弱模型可能无法关联。 * **解决**: 确保使用了高质量的 Embedding 模型 (如 `nvidia/nv-embed-v1`, `text-embedding-3-large`)。 5. **语言不匹配** * **现象**: 文档是英文,提问是中文。虽然现在的模型支持多语言,但同语言检索效果通常更好。 * **解决**: 尝试用文档相同的语言提问,或在 Embedding 前先翻译。 ### Q: `chat-model` 和 `embedding-model` 是否需要保持一致? **完全不需要,且通常是不一样的。** * **功能不同**: * **Embedding 模型** (如 `nvidia/nv-embed-v1`): 这是一个**翻译官**,只负责把文字翻译成数字(向量)。它通常是 Encoder-only 架构(类似 BERT),擅长理解语义相似度,但不会说话。 * **LLM 模型** (如 `llama-3.1-70b`): 这是一个**作家**,负责阅读上下文并生成回复。它是 Decoder-only 架构(类似 GPT),擅长逻辑推理和文本生成。 * **组合策略**: * 你可以混搭!比如用 OpenAI 的 `text-embedding-3` 做检索(便宜、快),但用 `Claude-3.5-Sonnet` 或 `Llama-3` 做回答(推理能力强)。 * **唯一约束**: 你的数据库里存储的向量是用哪个 Embedding 模型生成的,检索时就必须用**同一个** Embedding 模型处理问题,否则"语言不通"(坐标空间不一致)。 ### Q: LangChain4j 相比直接调用 API 有什么优势? 使用 LangChain4j 的优势包括: 1. **代码简化**: 无需手动处理 HTTP 请求、JSON 解析、错误处理等样板代码 2. **统一接口**: 轻松切换不同的 AI 提供商(OpenAI、NVIDIA、Anthropic 等) 3. **自动配置**: Spring Boot Starter 提供自动配置,开箱即用 4. **生态丰富**: 支持工具调用、函数调用、记忆管理、Agent 等高级功能 5. **更好的错误处理**: 内置重试机制和统一的异常处理 ## 项目结构 (Project Structure) ``` src/main/java/com/example/rag/ ├── RagApplication.java # 启动类 ├── config/ # 配置 (RagConfig) ├── controller/ # API控制器 (Document/Chat) ├── service/ # 核心业务 │ ├── RagService.java # RAG 编排逻辑 (最核心) │ ├── EmbeddingService.java # 向量生成 (基于LangChain4j) │ ├── LlmService.java # 大模型调用 (基于LangChain4j) │ └── DocumentService.java # 文档处理 ├── repository/ # 数据访问 (VectorRepository) ├── model/ # 数据模型 └── util/ # 工具类 (TextSplitter) ``` ## 架构说明 ### LangChain4j 集成 本项目使用 `langchain4j-open-ai-spring-boot-starter` 实现了与 OpenAI 兼容 API 的无缝集成: - **ChatLanguageModel**: 非流式对话 - **StreamingChatLanguageModel**: 流式对话(SSE) - **EmbeddingModel**: 文本向量化 这些 Bean 由 Spring Boot 自动配置并注入到服务类中,无需手动创建。 ### 服务层设计 - **LlmService**: 封装了 LangChain4j 的聊天模型调用,提供同步和流式两种接口 - **EmbeddingService**: 封装了 LangChain4j 的嵌入模型调用,支持单文本和批量文本向量化 - **RagService**: 协调检索和生成流程,将 Embedding 和 LLM 服务组合起来实现 RAG ### 配置管理 - **LangChain4j 配置**: AI 模型相关配置在 `langchain4j.open-ai` 节点下 - **业务配置**: RAG 相关配置在 `rag` 节点下(检索参数、切片参数等) ## 许可证 MIT License