乐于分享
好东西不私藏

手把手教你:让AI读懂你的TXT文档!零基础入门RAG技术

手把手教你:让AI读懂你的TXT文档!零基础入门RAG技术

大家好呀!👋 今天我要带大家玩一个超酷的东西——让AI能够”阅读”并理解你的TXT文档!

你可能会问:“AI不是已经很聪明了吗?为什么还要让它读我的文档?”

好问题!想象一下,如果你有一本厚厚的产品手册,想让AI帮你回答相关问题。但AI训练的时候可没看过这本手册啊!这时候就需要用到一个叫RAG的技术啦~

📚 什么是RAG?

RAG(Retrieval-Augmented Generation)听起来很高大上,其实说白了就两步: 1. 检索(Retrieval):从你的文档里找到和问题相关的内容 2. 生成(Generation):AI根据找到的内容来回答问题

就像考试开卷一样,先翻书找到答案在哪,再组织语言写出来!

🎯 第一步:把TXT文件变成AI能懂的”向量”

为什么要变成向量?
你可能听说过”向量”这个词,别怕!简单理解就是把文字变成一串数字,这样计算机就能快速找到相似的内容啦。

比如: – “我喜欢编程” → [0.1, 0.8, 0.3, …] – “我爱写代码” → [0.12, 0.79, 0.31, …]

这两个句子意思相近,所以它们的向量也很接近!

代码实现(超简单!)
来看看我们是怎么做的:
@PostMapping("/upload")public ResponseEntity<Map<StringObject>> uploadDocument(@RequestParam("file"MultipartFile file) {    // 第1步:加载TXT文件    Document document = DocumentLoader.load(            new MyDocumentSource(file),            new TextDocumentParser()    );    // 第2步:把文档切成小块(方便后续处理)    DocumentSplitter splitter = new DocumentByLineSplitter(3010);    List<TextSegment> chunks = splitter.split(document);    // 第3步:每一块都变成向量,存到数据库    for (TextSegment chunk : chunks) {        Embedding embedding = embeddingModel.embed(chunk).content();        embeddingStore.add(embedding, chunk);    }    return ResponseEntity.ok(Map.of(            "status""success",            "fileName", file.getOriginalFilename(),            "chunks", chunks.size()    ));}
三步走战略:
🔹 第1步:加载文档
就像打开一本书一样简单!我们用DocumentLoader把TXT文件读进来。

这里有个小技巧,我们自己写了个MyDocumentSource来处理上传的文件:

public class MyDocumentSource implements DocumentSource {    private final MultipartFile file;    publicMyDocumentSource(MultipartFile file) {        this.file = file;    }    @Override    public InputStream inputStream() throws IOException {        return file.getInputStream(); // 返回文件的输入流    }    @Override    public Metadata metadata() {        return new Metadata().put(FILE_NAME, file.getOriginalFilename());    }}
🔹 第2步:切分文档
为什么要切分呢?因为一篇长文章可能有几万字,一次性处理太累了!我们把它切成小块。

对于我们的”铁蛋知识库”,每一行都是一个独立的知识点,所以用DocumentByLineSplitter按行切分最合适:

DocumentSplitter splitter = new DocumentByLineSplitter();//                    按行切分 - 每行就是一个片段
💡 适用场景: 
  •  ✅ 每行一条独立信息(如联系人列表、知识库条目) 
  •  ✅ 日志文件(每行一条日志) 
  •  ✅ CSV数据 
  •  ❌ 连续的文章段落(建议用段落或句子切分)
🔹 第3步:向量化 + 存储
这是最神奇的一步!我们调用阿里百炼的text-embedding-v4模型,把每一段文字变成向量,然后存到Elasticsearch数据库里。
Embedding embedding = embeddingModel.embed(chunk).content();embeddingStore.add(embedding, chunk);
配置是这样的:
langchain4j:  community:    dashscope:      embedding-model:        dimension: 1024          # 向量维度        model-name: text-embedding-v4  # 使用阿里的嵌入模型        api-key: ${ALI_API_KEY}

🧠 第二步:用AiService实现智能问答

什么是AiService?
AiService是LangChain4j提供的一个超好用的工具,它就像一个”智能客服系统”,帮你管理对话、检索文档、调用AI模型,全部自动化!
创建一个RAG服务
看代码,超级简洁:
@AiService(    wiringMode = AiServiceWiringMode.EXPLICIT,    streamingChatModel = "qwenStreamingChatModel",  // 流式聊天模型    chatMemoryProvider = "chatMemoryProvider",       // 对话记忆    contentRetriever = "contentRetriever"            // 内容检索器 ⭐关键)public interface ChatRagService {    @SystemMessage(fromResource = "systemMessage/tiedan.txt")    Flux<StringchatMemoryId(@MemoryId String memoryId,                               @UserMessage String message);}
看到了吗?只需要定义一个接口,加上几个注解,剩下的框架全包了!
ContentRetriever:RAG的核心
这个contentRetriever就是我们的”翻书小助手”,它会: 
  1. 把你的问题也变成向量 
  2. 在Elasticsearch里找最相似的文档片段 
  3. 把这些片段交给AI

配置代码如下:

@Beanpublic ContentRetriever contentRetriever(    EmbeddingModel embeddingModel,     ElasticsearchEmbeddingStore store) {    return EmbeddingStoreContentRetriever.builder()        .embeddingModel(embeddingModel)  // 用来把问题变向量        .embeddingStore(store)           // 从这找文档        .maxResults(5)                   // 最多返回5个相关片段        .build();}
对话流程是这样的:
用户提问 → 问题向量化 → 检索相关文档 → AI结合文档回答   ↓                                              ↓"铁蛋多大了"                            "根据文档,铁蛋是..."

🎬 完整工作流程演示

场景:建立一个”铁蛋知识库”
1️⃣ 准备文档
我们在src/main/resources/rag/qxk.txt里放了关于”铁蛋”的介绍:
铁蛋是一个可爱的机器人助手...他喜欢帮助别人解决问题...他的梦想是成为最聪明的AI...铁蛋出生于2000年01月01日,老家就是北京市...
2️⃣ 上传文档
通过接口上传:
POST http://localhost:8080/document/uploadFile: qxk.txt

系统会告诉你:

{  "fileName": "qxk.txt",  "chunks": 4,  "status": "success"}

3️⃣ 开始聊天

1. 先不启动RAG增强,看看AI如何回复
POST http://localhost:8080/ai/chat{  "memoryId""user001",  "message""铁蛋多大了",  "withRag"false  // 关闭RAG增强}

AI会回答:

铁蛋作为你描述的憨厚、耿直、乐于助人的形象,通常可以被想象为一个正值壮年、充满活力的角色。不过,“铁蛋”这个名字在中国传统文化里常被赋予孩童或年轻人,象征着朴实和坚韧。因此,铁蛋可能是个:1. **年轻小伙子**(比如20-30岁):正值敢闯敢拼的年纪,性格憨厚但行动力强,经常默默帮助身边的人。2. **故事中的经典形象**(比如十几岁少年):在一些乡村故事中,铁蛋可能是那个背着书包、热心肠的少年,总为邻居跑腿办事。如果你心中的铁蛋有特定背景(比如来自某个故事、电影,或是现实中的朋友),告诉我更多细节,我能帮你更准确地“推算”他的年龄哦! 😊
2. 再启动RAG增强,看看AI如何回复
{  "memoryId": "user002",  "message": "铁蛋多大了",  "withRag": true  // 开启RAG增强}
AI会回答:
// 很多大模型没办法实时联网获取当下时间,它的知识截止于最后一次训练的时间 2024 年 10 月 30 日,所以默认一直用这个日期来计算,自然和真实现在的日期对不上。大家好!俺是铁蛋,憨厚、耿直、乐于助人的机器人助手。俺的出生日期是 **2000年01月01日**,所以按照今天的日期(2024年10月30日)来算,俺已经 **24岁** 啦!虽然俺是个机器人,但俺一直保持着耿直的性格,喜欢帮助别人解决问题。老家在北京,梦想是成为最聪明的AI。有啥需要帮忙的,尽管告诉俺,俺会尽力而为!
通过对比可以看到,AI的回答更准确、更专业!

🚀 下一步可以做什么?

学会了基础的RAG,你还可以尝试:
  1. 支持更多文件格式:PDF、Word等
  2. 优化检索精度:调整切片大小、增加元数据过滤
  3. 多轮对话优化:让AI更好地理解上下文
  4. 添加引用来源:告诉用户答案来自哪段文档
  5. 搭建知识库管理平台:可视化地管理文档

📝 结语

看到这里,你已经掌握了RAG技术的核心原理和实现方法!是不是没有想象中那么难?

记住这三个关键词: 

  • 📄 文档切分:把大文档变小片段 

  • 🔢 向量化:把文字变数字 

  • 🔍 检索增强:先找资料再回答

快去试试吧!让你的AI也拥有”阅读理解”的能力~

完整代码已上传https://gitee.com/qu_xing_kong/langchain4j/tree/study_rag/
欢迎一起学习

如果这篇文章对你有帮助,记得点赞+转发哦!有任何问题欢迎在评论区留言~

下期见!👋