LangChain:RAG开发
LangChai的核心理念: 为各种LLMS实现通用的接口
LangChain主要功能:
Prompts(优化提示词功能),Models(调用各类模型),History(管理会话历史记录),Indexes(管理和分析各类文档),Chains(构建功能的执行链条),Agent(构建智能体)
总结来说,LangChain提供了各种功能的API,LangChain是后续学习RAG开发的主力框架
LangChain安装(在终端执行即可):
pip install langchain langchain-community langchain-ollama dashscope chromadb
langchain:核心包
langchain-community: 社区支持包,提供了更多的第三方模型调用
langchain-ollama: Ollama支持包,支持调用Ollama托管部署的本地模型
dashscope: 阿里云通义千问的Python SDK
chromadb: 轻量向量数据库
RAG介绍:
基础大模型存在一些问题:
1.知识不是实时的
2. 知识是缺乏的,无法覆盖特定领域或高度专业化的内部知识
3. 幻觉问题,有时会在回答中生成看似合理但实际上是错误的信息
4.数据安全性
RAG即检索增强生成,为大模型提供了从特定数据源检索到信息,一次来修正和补充生成的答案,RAG=检索技术+LLM提示
检索是啥:
用户问题 ↓ 【1. 向量化】把问题转成向量 ↓ 【2. 相似度搜索】在向量库里匹配,找到最相似的top-k条(比如top-10) ↓ 【3. 组装上下文】把这k条内容直接放进提示词 ↓ 【4. 生成回答】大模型基于这些内容回答
RAG标准流程由索引,检索,和生成三个核心阶段组成。
索引阶段:通过处理多种来源多种格式的文档提取其中文本,将其切分为标准长度的文本块,并进行嵌入向量化,向量存储再向量数据库中。
检索阶段:用户输入的查询被转化为向量表示,通过相似度匹配从向量数据库中检索出最相关的文本块。
生成阶段:检索到的相关文本与原始查询共同构成提示词,输入大语言模型,生成精确且具备上下文关联的回答。
RAG流程中,向量库是一个重要的节点
离线流程:知识和信息--> 向量嵌入(向量化)--> 存入向量库
在线流程:用户的提问--> 向量嵌入(向量化)->在向量库中匹配
向量的基础概念:
它把一段文字的语义信息,转换成一串固定长度的数字列表.让计算机能看懂文字的含义并作相似度计算。
向量的计算(文本嵌入过程),可借助文本嵌入模型实现,如text-embedding-v1
向量的匹配通过算法实现,如余弦相似度
向量的维度表示一段文本在多个抽象语义特征来描述文本
啥事余弦相似度
余弦相似度主要匹配的就是:同向(无所谓长度)
余弦相似度--> 两个向量的点积➗两个向量模长的乘积
import numpy as np #计算点积 def get_dot(vec_a,vec_b): if len(vec_a) != len(vec_b): raise ValueError("2个向量的维度数量相似") dot_sum = 0 for a,b in zip(vec_a,vec_b): dot_sum += a*b return dot_sum def get_norm(vec): """计算单个向量的模长""" sum_square = 0 for i in vec: sum_square += i**2 return np.sqrt(sum_square) def cosine_similarity(vec_a,vec_b): result = get_dot(vec_a,vec_b)/(get_norm(vec_a)*get_norm(vec_b)) return result if __name__ == '__main__': vec_a = [0.5,0.5] vec_b = [0.7,0.7] vec_c = [0.7,0.5] vec_d = [-0.6,-0.5] print("ab",cosine_similarity(vec_a,vec_b)) print("ac",cosine_similarity(vec_a,vec_c)) print("ad",cosine_similarity(vec_a,vec_d))
LangChain访问本地大模型:
from langchain_ollama import OllamaLLM model = OllamaLLM(model = "deepseek-r1:1.5b") res = model.invoke(input = "你是谁呀能做什么?") print(res)model 后面跟的大模型要是自己下载的
LangChain访问阿里云通义千问大模型
# langchain_community from langchain_community.llms.tongyi import Tongyi model = Tongyi(model = "qwen-max") res = model.invoke(input = "你是谁呀能做什么") print(res)langchain_community 提供了许多的第三方,所以从这个导包。
另外没有api_key是因为系统环境配置了,这是为了安全,如果没有配置,就在model前面加上api_key然后输入的密钥就行
模型的流失输出:
在我们用的时候,ai回答我们的时候总是直接把整个语句给我们了,如果语句过长用户就会等较长的时间,体验感较差。
在我们用网页版的豆包和Deepseek的时候它们是慢慢的给我们回复的,这就是流式输出
invoke方法: 一次性返回完整结果
stream方法: 逐段返回结果,流式输出
# 导包4 from langchain_community.llms.tongyi import Tongyi model = Tongyi(model = "qwen-max") res = model.stream(input = "你是谁呀能做什么?") for chunk in res: print(chunk, end="", flush=True)end 则是将每个文本后面的换行符改成“”,不至于每输出一段后就换行
同时flush刷新缓存区
Chat Models(聊天模型):
聊天消息包含下面几种类型,使用时需要按照约定传入合适的值:
AIMessage: 就是AI输出的消息,可以是针对问题的回答
HumanMessage: 用户消息,我们给LLMs的提示信息
SystemMessage: 可以用于指定模型具体所处的环境和背景,如角色扮演
from langchain_community.chat_models.tongyi import ChatTongyi from langchain_core.messages import HumanMessage,AIMessage,SystemMessage model = ChatTongyi(model = "qwen3-max") messages = [ SystemMessage(content="你是一个边塞诗人"), HumanMessage(content="写一首唐诗"), AIMessage(content="按照你上一个回复的格式,再写一首唐诗"), HumanMessage(content="按照你上一个回复的格式,在写一首唐诗"), ] res = model.stream(input = messages) # for循环迭代打印输出,通过.content来获取内容,因为我们这是聊天模型,而不是大语言模型 for chunk in res: print(chunk.content, end="", flush=True)消息的简写模式
messages = [
("system","你是一个边塞诗人。")
("human","写一首唐诗"),
("ai",“锄禾.....”)
]
通过2元元组封装信息;
第一个元素为角色
字符串: system/human/ai
第二个元素为内容
两种写法的优劣
第一种写法,是静态的,一步到位,直接得到了Message类的类对象
第二种写法,是动态的,需要在运行时,由LangChain内部机制转换为Message类对象
由于是动态的,所以在简写形式支持内部填充{变量}占位
Embeddings Models(文本嵌入模型)
文本嵌入模型的特点: 将字符串作为输入,返回一个浮点数的列表(向量).
在NLP中,Embedding的作用就是将数据进行文本向量化
from langchain_community.embeddings import DashScopeEmbeddings # 创建模型对象,不传model默认用的是 text-embedding -v1 model = DashScopeEmbeddings() print(model.embed_query("我喜欢你")) print(model.embed_documents(["我喜欢你", "你喜欢我吗?"]))DashScopeEmbeddings里面输入自己API_KEY
embed_query 单词转化,而embed_documents是批量转化
如果是本地的呢?
只需要
from langchain_ollama import OllamaEmbeddings
OllamaEmbeddings(model = "qwen3-embedding:4b") //这里自己的聊天模型就行
