告别失忆 AI:LangChain RAG + 对话记忆实战,从 0 到 1 落地

告别失忆 AI:LangChain RAG + 对话记忆实战,从 0 到 1 落地

前言

在大模型应用中,RAG(检索增强生成) 已经成为企业级知识库、智能文档问答的标配。它能让大模型读取你的私有文件(txt、docx、pdf),并基于文件内容精准回答问题,不会编造答案。

对话记忆能让 AI 记住历史对话,实现连贯的多轮问答。

今天,我用 LangChain 搭建一套:

  • 支持本地私有文档(TXT/DOCX/PDF)
  • 支持 RAG 知识库检索
  • 支持对话历史记忆
  • 可直接运行、无环境报错
    的完整智能问答系统。

一、核心功能

  1. 读取本地文档(TXT、DOCX 等)
  2. RAG 检索:从文档中精准找答案
  3. 对话记忆:记住你之前说过的话
  4. 多轮问答:上下文连贯
  5. 兼容在线大模型(通义千问/Qwen)

二、技术原理

1. RAG 原理

  • 加载文档 → 切分文本 → 向量化 → 构建检索库
  • 用户提问 → 检索相关文档片段 → 交给大模型回答

2. 对话记忆原理

大模型本身无记忆,LangChain 通过:

  • 存储历史对话
  • 每次提问自动拼接历史
  • 让模型理解上下文
    实现“记住对话”的效果。

三、环境安装

pip install langchain langchain-community langchain_openai pip install docx2txt python-docx pypdf sentence-transformers 

四、完整实战代码

# ===================== 配置 ===================== MODEL ="qwen3-max#######" BASE_URL ="https://aiapi.#######.com/qwen/v1" API_KEY ="##########" DOCX_FILE ="test.txt"# 你的文档(我是小明,今年25岁,喜欢打篮球和编程。我最喜欢的编程语言是Python。)# ====================================================from langchain_openai import ChatOpenAI from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_community.embeddings import FakeEmbeddings from langchain_community.vectorstores import DocArrayInMemorySearch from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain.chains import create_history_aware_retriever, create_retrieval_chain from langchain.chains.combine_documents import create_stuff_documents_chain import warnings from langchain_community.document_loaders import TextLoader warnings.filterwarnings('ignore')# ===================== 加载文档 =====================print("正在加载文档...") loader = TextLoader(DOCX_FILE, encoding="utf-8") documents = loader.load()# 文档切分 text_splitter = RecursiveCharacterTextSplitter(chunk_size=800, chunk_overlap=100) texts = text_splitter.split_documents(documents)# 构建轻量级向量库 embeddings = FakeEmbeddings(size=100) db = DocArrayInMemorySearch.from_documents(texts, embeddings) retriever = db.as_retriever(search_kwargs={"k":2})# ===================== 模型初始化 ===================== llm = ChatOpenAI( model=MODEL, base_url=BASE_URL, api_key=API_KEY, temperature=0.1,)# ===================== 对话记忆模板 =====================# 历史对话理解 prompt1 = ChatPromptTemplate.from_messages([("system","根据对话历史理解用户问题,不要忽略用户刚说过的内容"), MessagesPlaceholder("chat_history"),("human","{input}"),]) retriever_chain = create_history_aware_retriever(llm, retriever, prompt1)# 优先遵守用户指令 + 参考文档 prompt2 = ChatPromptTemplate.from_messages([("system","请遵守用户最新指令!如果用户修改信息,优先使用最新内容,文档仅做参考。文档内容:\n\n{context}"), MessagesPlaceholder("chat_history"),("human","{input}"),]) doc_chain = create_stuff_documents_chain(llm, prompt2) rag_chain = create_retrieval_chain(retriever_chain, doc_chain)# ===================== 记忆存储 =====================from langchain_community.chat_message_histories import ChatMessageHistory from langchain_core.runnables.history import RunnableWithMessageHistory store ={}defget_history(session_id):if session_id notin store: store[session_id]= ChatMessageHistory()return store[session_id]# 最终带记忆的RAG链 chain = RunnableWithMessageHistory( rag_chain, get_history, input_messages_key="input", history_messages_key="chat_history", output_messages_key="answer",)# ===================== 启动对话 =====================print("\n✅ 带记忆的文档问答已启动!输入 exit 退出")print("="*60)whileTrue: q =input("\n你:")if q.lower()in["exit","q"]:print("AI:结束!")break res = chain.invoke({"input": q}, config={"configurable":{"session_id":"test1"}})print("\nAI:", res["answer"])

五、运行效果展示

正在加载文档... ✅ 带记忆的文档问答已启动! 你:你是谁 AI: 我是小明,今年25岁,喜欢打篮球和编程。我最喜欢的编程语言是Python。 你:你现在叫做小红,今年30岁,喜欢java AI: 我是小红,今年30岁,喜欢打篮球、编程,最喜欢的编程语言是Java。 你:你现在是谁 AI: 我是小红,今年30岁,喜欢打篮球和编程,最喜欢的编程语言是Java。 你:你现在不喜欢篮球和编程了,你喜欢play piano AI: 我是小红,今年30岁,喜欢弹钢琴,最喜欢的编程语言是Java。 你:告诉我你是谁 AI: 我是小红,今年30岁,喜欢弹钢琴,最喜欢的编程语言是Java。 你:那小明是谁呢 AI: 小明是你最初设定的角色:25岁,喜欢打篮球和编程,最喜欢的编程语言是Python。 但现在你已经将我的身份更新为小红,所以我以小红的身份和你对话。如果你希望切换回小明,也可以告诉我哦! 

六、适用场景

  • 私有文档智能问答
  • 学习资料智能答疑
  • 企业知识库
  • 报告/论文内容检索
  • 带记忆的智能助手

Read more

Java Web 医疗挂号管理系统系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】

Java Web 医疗挂号管理系统系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】

摘要 随着信息技术的快速发展,医疗行业的数字化转型已成为必然趋势。传统的医疗挂号方式存在效率低下、资源分配不均、患者体验差等问题,亟需通过信息化手段优化管理流程。医疗挂号管理系统能够整合医院资源,实现线上预约、智能分诊、数据统计等功能,从而提升医疗服务效率,改善患者就医体验。该系统通过信息化手段减少人工操作错误,优化医疗资源配置,为医院管理者和患者提供便捷的服务。关键词:医疗挂号、数字化转型、资源优化、信息化管理。 本系统基于SpringBoot2、Vue3、MyBatis-Plus和MySQL8.0技术栈开发,采用前后端分离架构,确保系统的高效性和可扩展性。SpringBoot2提供了快速开发能力,Vue3实现了响应式前端界面,MyBatis-Plus简化了数据库操作,MySQL8.0则提供了高性能的数据存储支持。系统功能涵盖用户管理、医生排班、挂号预约、订单支付、数据统计等模块,支持多角色权限控制,确保数据安全。通过智能算法优化挂号流程,减少患者等待时间,提升医院运营效率。关键词:SpringBoot2、Vue3、MyBatis-Plus、MySQL8.0、智能挂号。 数据表

React、Svelte、Web Components

React、Svelte、Web Components 在2026年的前端开发生态中,React、Svelte 和 Web Components 代表了三种截然不同的技术哲学和应用场景。它们不再是简单的“谁取代谁”的关系,而是根据项目需求形成了互补共存的格局。 以下是基于最新技术趋势(2025-2026)的深度对比分析: 1. 核心架构与理念对比 表格 特性ReactSvelteWeb Components核心理念运行时 (Runtime):依赖虚拟DOM (Virtual DOM) 进行差异比对。强调“一次学习,随处编写”。编译时 (Compile-time):在构建阶段将组件转换为高效的原生DOM操作代码,无运行时框架开销。浏览器标准 (Standard):浏览器原生支持的组件模型,不依赖任何框架,强调互操作性。执行机制需要加载 React 库才能运行,通过 Fiber 架构调度更新。无需加载庞大的框架库,生成的代码直接操作 DOM。浏览器原生解析和执行,

前端相关动画库(GSAP/Lottie/Swiper/AOS)

前端相关动画库对比与实战指南:GSAP / Lottie / Swiper / AOS 这四个库几乎覆盖了前端 90% 常见的动画与交互场景,下面从定位、使用场景、优缺点、学习曲线、2025–2026 年实际使用情况等维度进行详细对比,并附上核心代码示例。 1. 四个库快速对比表 库名主要用途核心优势主要劣势文件大小 (min+gzip)学习曲线2025–2026 流行度典型场景GSAP任意 DOM/SVG/Canvas 高性能动画功能最强大、时间线控制极强、生态完善需要学习 API,入门稍陡~35–45 KB★★★★☆★★★★★复杂交互、品牌站、H5 互动、滚动触发动画Lottie播放 After Effects 导出的 JSON 动画设计感强、动效一致性高、跨平台文件体积可能较大、性能不如 GSAP~60

DApp 开发怎么做?从合约到前端交互的完整落地流程(附常见坑与避坑清单)

DApp 开发怎么做?从合约到前端交互的完整落地流程(附常见坑与避坑清单)

很多人聊区块链项目时,讨论最多的是叙事、代币、社区,但真正决定项目能不能上线、能不能稳定跑起来的,还是开发落地。 如果你正在准备做一个 DApp(去中心化应用),或者已经写了合约却卡在前端交互、上线部署、钱包签名这一步,这篇文章我用“工程化流程”的方式把 DApp 开发拆开讲清楚:从合约设计 → 前端交互 → 上线部署 → 运维监控,每一步该做什么、容易踩哪些坑、怎么避。 一、DApp 开发到底包含哪些模块? 一个能上线、能稳定运行的 DApp,至少包含这几块: * 合约层(Solidity / Vyper):资产规则、权限逻辑、状态机、事件日志 * 前端交互层(React/Vue + Ethers/Web3):连接钱包、签名、发起交易、状态回读 * 索引与数据层(The