SEO技术

SEO技术

Products

当前位置:首页 > SEO技术 >

Spring AI RAG实战,构建企业智能问答系统秘诀何在?

96SEO 2026-08-09 23:21 0


Spring AI + RAG实战:建立公司级智能问答程序

说到前言,为什么你的AI总是不“懂”你的业务?

很多团队接入了AI后发现一个尴尬的问题:AI回答得头头是道,但跟你的业务完全没关系。

”AI答这方面,“方式如下…,”这就是典型的知识缺失问题。AI预训练时根本不知道你公司的规章制度,需要通过RAG把知识注入进去。

RAG = Retrieval + Augmentation + Generation

使用者痛点直击

  • 信息孤岛:公司内部文档分散在不同程序,搜索成本高。
  • 答案不准:传统ChatGPT只能基于公开语料,无法回答内部制度或技术细节。
  • 缺少溯源:业务决策需要明确引用来源,普通大模型无法提供文档引用。
  • 维护成本高:每次制度更新都要手动重新训练模型或重新部署。
  • L​atency & 成本:SaaS大模型调用费用高且响应慢,无法满足公司内部大量并发。

今天这篇文章。我用一个完整的公司内部知识问答程序案例,带你从0到1掌握Spring AI RAG开发,让上述痛点迎刃而解。

一、项目需求与架构设计

业务场景

某科技公司需要一个内部知识问答程序,让员工可以:

  • 用自然语言查询公司制度、流程文档、技术规范;
  • 快速找到相关政策,不用在海量文档里翻找;
  • 答案带有原文引用,方便溯源。

程序架构


┌─────────────────────────────────────────────────────────────────┐
│ 使用者查询界面 │
│ │
└────────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Spring Boot 应用 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ REST API │ │ ChatClient│ │ Document │ │ Vector Search │ │
│ │ Controller│ │ │ │ Loader │ │ Service │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────────────┘ │
└────────────────────────────┬────────────────────────────────────┘
┌────────────────────╂─────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Milvus向量库 │ │ 文档存储 │ │ 通义Qwen API │
│ │ │ │ │ │
└───────────────┘ └───────────────┘ └───────────────┘

技术选型

  • Sprint AI: 提供统一的Embedding/Chat抽象;
  • Milvus v2.x: 高性能向量检索,引擎支持过滤和混合搜索;
  • L​LM - 通义千问 Qwen‑plus : 国内可商用的大模型,支持流式输出;说起来,
  • Docker Compose + Spring Boot : 一键本地/私有云部署。

二、环境搭建:Docker Compose一键部署

目录结构


company-kb/
├── docker-compose.yml
├── spring-ai-kb-app/
│ ├── src/main/java/com/company/kb/
│ │ ├── CompanyKbApplication.java
│ │ ├── config/
│ │ │ ├── AiConfig.java
│ │ │ └── MilvusConfig.java
│ │ ├── controller/
│ │ │ ├── ChatController.java
│ │   │   ├── DocumentController.java
│   │   ├── service/
│   │   │   ├── RagService.java
│   │   │   ├── DocumentService.java
│   │   │   └── EmbeddingService.java
│   │   ├── model/
│   │   │   ├── DocumentChunk.java
│   |   |   ├── ChatRequest.java
│   |   └─ loader/
│            ├── PdfLoader.java
│            ├── WordLoader.java …├── src/main/resources/
| └─ application.yml
├── documents/ # 原始文档目录
└── embeddings/ # 嵌入缓存

Docker Compose 配置


# docker-compose.yml
version: '3.8'
services:
# Milvus 向量数据库
milvus-etcd:
至于image,quay.io/coreos/etcd:v3.5.9
environment:
- ETCD_AUTO_COMPACTION_MODE=revision
- ETCD_AUTO_COMPACTION_RETENTION=1000
- ETCD_QUOTA_BACKEND_BYTES=4294967296
volumes:
- ./volumes/etcd:/etcd
command: etcd --advertise-client-urls=http://0.0.0.0:2379 \
--listen-client-urls http://0.0.0.0:2379 \
--data-dir /etcd
milvus-minio:
image的观点是,minio/minio:RELEASE.2024-03-01T08-12-52Z
environment:
MINIO_ROOT_USER: minioadmin
MINIO_ROOT_PASSWORD: minioadmin
volumes:
- ./volumes/minio:/minio_data
command: minio server /minio_data
milvus-standalone:
再看image,milvusdb/milvus:v2.4.5
container_name: milvus-standalone
说到ports,- "19530:19530"
- "9091:9091"
volumes:
- ./volumes/milvus:/var/lib/milvus
environment:
ETCD_ENDPOINTS: milvus-etcd:2379
MINIO_ADDRESS: milvus-minio:9000
depends_on:
- milvus-etcd
- milvus-minio
restart: always
# Spring AI 应用
spring-ai-kb:
从build来看,./spring-ai-kb-app
container_name: spring-ai-kb
再看ports,- "8080:8080"
environment:
- SPRING_AI_ALIBABA_API_KEY=${ALI_API_KEY}
volumes:
- ./documents:/data/documents
depends_on:
- milvus-standalone
restart: always
networks:
default:
name这方面,milvus-network

*启动命令*


# 启动所有服务
docker-compose up -d
# 查看运行状态
docker-compose ps
# 看日志
docker-compose logs -f spring-ai-kb

三、主要配置:application.yml 完整示例


说到spring。application:
name的观点是,company-kb-system
servlet:
multipart:
max-file-size: 100MB # 单文件最大100MB
max-request-size: 500MB # 单次请求最大500MB
从ai来看,alibaba:
api-key: ${ALI_API_KEY}
base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
说到chat,options:
从model来看,qwen-plus # 大模型选择
temperature: 0.1 # RAG 场景低温度保证准确性
max-tokens: 2048
embedding:
options:
从model来看,text-embedding-v4 # 嵌入模型
spring.ai.vectorstore.milvus:
client这方面,host: localhost # Docker 内部网络默认 localhost
再看port,19530 # Milvus 默认端口
从app来看,storage:
documents: /data/documents # 挂载到容器内的文档目录
--- # 可选的嵌入缓存方法
server的观点是,port :8080
logging.level:
org.springframework.ai : DEBUG
com.company.kb : DEBUG

四、文档处理:多格式支持与智能分块

文档分块策略

The quality of chunking decides ~80% of RAG performance.

策略 块大小 重叠 适用场景
固定字数 500 字 50 字 通用场景
段落分块 按段落边界 0 字 结构清晰的手册/规章制度 语义分块 ≈100 字 20 字 高度语义化内容,如研发方案或代码注释

统一文档加载器接口


package com.company.kb.loader;import org.springframework.stereotype.Component;import org.springframework.web.multipart.MultipartFile;import java.io.IOException;老实说,import java.nio.file.Path;import java.util.List;老实说,/** 文档加载器统一接口 */
public interface DocumentLoader {
boolean supports;List load throws IOException;说起来,}

PDF 加载器


@Component
public class PdfLoader implements DocumentLoader {
@Override public boolean supports {
return fileName.toLowerCase.endsWith;...
private List smartChunk {
// 清理 & 按段落切分 → 合并形成适当大小块 + 重叠保留上下文 ...
}
...
}

Word 加载器


@Component public class WordLoader implements DocumentLoader {
...
private List smartChunk{
// 基于句子边界进行截断并保留 overlap ...
}
...
}

Markdown 加载器


@Component public class MdLoader implements DocumentLoader {
...
private List chunkBySection{
// 按标题拆分 → 必要时再细粒度切块 …}
...
}

五、向量存储:Milus 配置与写入流程 

Milus 配置类 


package com.company.kb.config;import io.milvus.client.MilvusClient;话说回来,import io.milvus.param.ConnectParam;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configuration public class MilvusConfig {
@Value private String host;@Value private int port;@Bean public MilusClient milusClient {
return new MilusClient
.withHost
.withPort
.build);}
}
...

文档上传 & 向量写入服务 


@Service @RequiredArgsConstructor @Slf4j public class DocumentService {
private final List loaders;private final EmbeddingModel embeddingModel;@Value private String documentsPath;private VectorStore vectorStore;@PostConstruct public void init{
this.vectorStore = MilusVectorStore.builder)
.collectionName
.dimension // text‑embedding‑v4维度固定为1024
.build;}
public UploadResult uploadDocument throws Exception{
// 保存原始文件 → 找到对应 loader → 分块 → 构造 Document 带元数据 → 写入向量库 …}
...
}
...

六、RAG 问答:多路召回 & 智能重排 

传统 RAG 的两大坑 

  1. 语义漂移 – 向量相似 ≠ 真正相关;
  2. 上下文不足 – 单轮检索可能遗漏关键细节。按理说,
    从解决思路来看。多路召回+重排序,让「相关性」变「可解释」!mermaid graph LR A --> B A --> C A --> D B & C & D --> E E --> F F --> G ​ ​ ​ ​ ​ ​​ ​ ​\t\t\t\t\t\t\t\t \r\r\r\r

多路召回实现

java @Service @RequiredArgsConstructor@Slf4j public class MultiRetrieverService {

private final VectorStore vectorStore;private final EmbeddingModel embeddingModel;

/** 多路召回 */ public List multiRetrieve{ List results = new ArrayList<>; results.addAll);results.addAll);results.addAll);// 去重 && 重排 return rerank(query。results.stream.distinct.collect),topK);}

/** 向量语义检索 */ private List vectorRetrieve{...}

/** 简易关键词匹配 */ private List keywordRetrieve{...}

/** 同源元数据补齐 */ private List metadataRetrieve{...}

/** 重排 – 用交叉编码得分 */ private List rerank{ return candidates.stream .map。c.metadata,c.source,calculateRelevance))) .sorted-> Double.compare,a.score)) .limit.collect);怎么说呢,} ... }

完整 RAG 问答服务

private final ChatClient chatClient;private final MultiRetrieverService retriever;话说回来,

/** 主入口 – 问答 */ public RagAnswer answer{ long start = System.currentTimeMillis;List chunks = retriever.multiRetrieve;

 if){
return new RagAnswer。null,System.currentTimeMillis-start);说起来,

}

// 构造上下文 —— 自动截断防止 token 爆炸 String context = buildContext;

// Prompt 工程—— 强制要求引用来源、不编造内容 String prompt = buildPrompt;怎么说呢,

String answer;按理说,try{ answer = chatClient.prompt.user.call.content;} catch{ log.error;说起来,answer = "服务暂不可用,请稍后再试";}

return new RagAnswer(answer。buildSources,chunks.size,System.currentTimeMillis-start);}

/* 辅助方法 …说起来,buildContext / buildPrompt / estimateTokens …*/ }

流式 RAG

java public Flux answerStream{ List chunks = retriever.multiRetrieve;话说回来,String prompt = buildPrompt(question。buildContext);

 return chatClient.prompt
.user
.stream
.content;怎么说呢,// SSE 输出每个 token 块

}

七 、REST API :完整问答程序接口

控制层

java @RestController @RequestMapping @RequiredArgsConstructor public class KnowledgeBaseController {

private final RagService ragService;private final DocumentService documentService;

/** 问答入口 */ @PostMapping public RagAnswer ask{ return ragService.answer);}

/** 流式返回 */ @PostMapping(value="/ask/stream",produces=MediaType.TEXTEVENTSTREAM_VALUE) public Flux askStream{ return ragService.answerStream);}

/** 文档上传 */ @PostMapping public DocumentService.UploadResult upload MultipartFile f) throws Exception{ return documentService.uploadDocument;}

/* …其他查询·删除等,*/ }

前端调用示例

javascript // 简单 fetch 示例 async function ask{ const q=document.getElementById.value;const r=await fetch('/api/kb/ask',{ method的观点是,'POST'。headers:{'Content-Type':'application/json'},body:`{"question":"${q}"}`});const d=await r.json;其实,document.getElementById.innerText=d.answer;// 展示来源 document.getElementById.innerHTML = d.sources.map(s=>`

${s.source}

${s.excerpt}

`).join;话说回来,}

八 、生产级调整

性能加速

java @Async // 异步上传。明显提高吞吐 public CompletableFutureUploadResult<\/span> uploadAsync{…说起来,}

public void batchEmbed{…} // 批处理一次性算多个向量

@Bean CacheManager cacheManager{return new ConcurrentMapCacheManager;} @Cacheable\") public float embedWithCache{return embeddingModel.embed;}

安全防护

java @Configuration public class SecurityConfig{

@Bean SecurityFilterChain filterChainthrows Exception{ return http.csrf) .authorizeHttpRequests(auth->auth .requestMatchers.aunticated .requestMatchers.hasRole ) .httpBasic) .build;} }

可观测性

java @Bean MeterRegistry meterRegistry{ return new PromeusMeterRegistry;}

private void recordMetrics{ meterRegistry.counter.increment;meterRegistry.timer .record,TimeUnit.MILLISECONDS);}

九 、效果测试

常见测试脚本

bash

curl -X POST -F "file=@./docs/年假制度.pdf" http://localhost/api/kb/upload

curl -X POST -H "Content-Type:" application/json \ -d '{"question":"我的年假有多少天?"}' \ http这方面,//localhost/api/kb/ask

curl -X POST -H "Content-Type:" application/json \ -d '{"question":"请详细说公司的请假流程"}' \ 从http来看。//localhost/api/kb/ask/stream | while read line;do echo "$line";done

效果评估指标

# 指标 # 含义 # 阈值目标 
召回率  相关文档被成功检出的比例  %95 
准确率  返回结果确实匹配使用者意图的比例  %92 
响应时延  从提问到得到完整答案所耗时间<𢙑 s <𢙑 s
Token 消耗&$ 成本  每千次对话平均 token 使用情况及对应费用 <$$10/月

十 、与

这篇文章主要要点

RAG 程序 = 文档处理 + 向量嵌入 + 检索 + LLM生成关键技术点: ├─ 智能分块 ├─ 向量存储 ├─ 多路召回 ├─ 重排序 ├─ Prompt工程 ╰─ 流式输出

接下来进阶方向

#方向#实现思路#价值说明

PDF OCR 引入 Tesseract 或阿里云 OCR。将扫描件转成可检索文本 解决纸质规章无法直接加载的问题

多语言支撑 Embedding 多语言模型+跨语言检索插件 覆盖外资子公司或英文技术手册

知识图谱提高 抽取实体关系写入 Neo4j 并做图谱检索 提供更深层次推理和关联查询

主动学习 & Feedback Loop 收集使用者点击反馈自动微调权重 长期召回质量

★☆☆☆☆ Agent 模式 集成工具调用如 Jira 创建工单等 实现真正业务助理

🚀 如果这篇文章对你有帮助,请点赞收藏!任何疑问欢迎在评论区交流 🙏‍♀️.


标签: 企业级

SEO优化服务概述

作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。

百度官方合作伙伴 白帽SEO技术 数据驱动优化 效果长期稳定

SEO优化核心服务

网站技术SEO

  • 网站结构优化 - 提升网站爬虫可访问性
  • 页面速度优化 - 缩短加载时间,提高用户体验
  • 移动端适配 - 确保移动设备友好性
  • HTTPS安全协议 - 提升网站安全性与信任度
  • 结构化数据标记 - 增强搜索结果显示效果

内容优化服务

  • 关键词研究与布局 - 精准定位目标关键词
  • 高质量内容创作 - 原创、专业、有价值的内容
  • Meta标签优化 - 提升点击率和相关性
  • 内容更新策略 - 保持网站内容新鲜度
  • 多媒体内容优化 - 图片、视频SEO优化

外链建设策略

  • 高质量外链获取 - 权威网站链接建设
  • 品牌提及监控 - 追踪品牌在线曝光
  • 行业目录提交 - 提升网站基础权威
  • 社交媒体整合 - 增强内容传播力
  • 链接质量分析 - 避免低质量链接风险

SEO服务方案对比

服务项目 基础套餐 标准套餐 高级定制
关键词优化数量 10-20个核心词 30-50个核心词+长尾词 80-150个全方位覆盖
内容优化 基础页面优化 全站内容优化+每月5篇原创 个性化内容策略+每月15篇原创
技术SEO 基本技术检查 全面技术优化+移动适配 深度技术重构+性能优化
外链建设 每月5-10条 每月20-30条高质量外链 每月50+条多渠道外链
数据报告 月度基础报告 双周详细报告+分析 每周深度报告+策略调整
效果保障 3-6个月见效 2-4个月见效 1-3个月快速见效

SEO优化实施流程

我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:

1

网站诊断分析

全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。

2

关键词策略制定

基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。

3

技术优化实施

解决网站技术问题,优化网站结构,提升页面速度和移动端体验。

4

内容优化建设

创作高质量原创内容,优化现有页面,建立内容更新机制。

5

外链建设推广

获取高质量外部链接,建立品牌在线影响力,提升网站权威度。

6

数据监控调整

持续监控排名、流量和转化数据,根据效果调整优化策略。

SEO优化常见问题

SEO优化一般需要多长时间才能看到效果?
SEO是一个渐进的过程,通常需要3-6个月才能看到明显效果。具体时间取决于网站现状、竞争程度和优化强度。我们的标准套餐一般在2-4个月内开始显现效果,高级定制方案可能在1-3个月内就能看到初步成果。
你们使用白帽SEO技术还是黑帽技术?
我们始终坚持使用白帽SEO技术,遵循搜索引擎的官方指南。我们的优化策略注重长期效果和可持续性,绝不使用任何可能导致网站被惩罚的违规手段。作为百度官方合作伙伴,我们承诺提供安全、合规的SEO服务。
SEO优化后效果能持续多久?
通过我们的白帽SEO策略获得的排名和流量具有长期稳定性。一旦网站达到理想排名,只需适当的维护和更新,效果可以持续数年。我们提供优化后维护服务,确保您的网站长期保持竞争优势。
你们提供SEO优化效果保障吗?
我们提供基于数据的SEO效果承诺。根据服务套餐不同,我们承诺在约定时间内将核心关键词优化到指定排名位置,或实现约定的自然流量增长目标。所有承诺都会在服务合同中明确约定,并提供详细的KPI衡量标准。

SEO优化效果数据

基于我们服务的客户数据统计,平均优化效果如下:

+85%
自然搜索流量提升
+120%
关键词排名数量
+60%
网站转化率提升
3-6月
平均见效周期

行业案例 - 制造业

  • 优化前:日均自然流量120,核心词无排名
  • 优化6个月后:日均自然流量950,15个核心词首页排名
  • 效果提升:流量增长692%,询盘量增加320%

行业案例 - 电商

  • 优化前:月均自然订单50单,转化率1.2%
  • 优化4个月后:月均自然订单210单,转化率2.8%
  • 效果提升:订单增长320%,转化率提升133%

行业案例 - 教育

  • 优化前:月均咨询量35个,主要依赖付费广告
  • 优化5个月后:月均咨询量180个,自然流量占比65%
  • 效果提升:咨询量增长414%,营销成本降低57%

为什么选择我们的SEO服务

专业团队

  • 10年以上SEO经验专家带队
  • 百度、Google认证工程师
  • 内容创作、技术开发、数据分析多领域团队
  • 持续培训保持技术领先

数据驱动

  • 自主研发SEO分析工具
  • 实时排名监控系统
  • 竞争对手深度分析
  • 效果可视化报告

透明合作

  • 清晰的服务内容和价格
  • 定期进展汇报和沟通
  • 效果数据实时可查
  • 灵活的合同条款

我们的SEO服务理念

我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。

提交需求或反馈

Demand feedback