文章目录

一、langChain 介绍
LangChain 是一个基于语言模型的框架,用于构建聊天机器人、生成式问答(GQA)、摘要等功能。它的核心思想是将不同的组件“链”在一起,以创建更高级的语言模型应用。LangChain就像一个超级连接器,可以轻松和各种外部工具(比如API、搜索引擎)对接。比如,想让聊天机器人能查询天气,只需要把天气API和LangChain连接起来,它就能帮你搞定。这样,你的应用功能会更强大,而且不需要自己去写复杂的代码。
LangChain 的主要价值在于以下几个方面:
- 组件化:LangChain 框架提供了用于处理语言模型的抽象组件,以及每个抽象组件的一系列 实现。这些组件具有模块化设计,易于使用,无论是否使用 LangChain 框架的其他部分,都 可以方便地使用这些组件。
- 现成的链式组装:LangChain 框架提供了一些现成的链式组装,用于完成特定的高级任务。这 些现成的链式组装使得入门变得更加容易。对于更复杂的应用程序,LangChain 框架也支持 自定义现有链式组装或构建新的链式组装。
- 简化开发难度:通过提供组件化和现成的链式组装,LangChain 框架可以大大简化大语言模 型应用的开发难度。开发人员可以更专注于业务逻辑,而无需花费大量时间和精力处理底层 技术细节。
二、环境安装
1.依赖库安装
需要安装以下包:
langchain-ollama
: 用于集成 Ollama 模型到 LangChain 框架中langchain
: LangChain 的核心库,提供了构建 AI 应用的工具和抽象langchain-community
: 包含了社区贡献的各种集成和工具Pillow
: 用于图像处理,在多模态任务中会用到faiss-gpu
: 用于构建简单 RAG 检索器
安装命令如下
pip install langchain-ollama langchain langchain-community Pillow faiss-gpu -i https://pypi.tuna.tsinghua.edu.cn/simple
2.下载模型
以llama3.1 为例,下载方式为
ollama pull llama3.1
如果需要部署其他的模型,可以 https://ollama.ai/library 了解所有可用的模型,通过 ollama pull <name-of-model>
命令获取。
三、基本使用示例
1.使用 ChatPromptTemplate 进行对话
示例代码如下
from langchain_ollama import ChatOllama # 添加库
from langchain_core.prompts import ChatPromptTemplate # 添加库
template = """
你是一个乐于助人的AI,擅长于解决回答各种问题。
问题:{question}
"""
model = ChatOllama(model="qwen05b", temperature=0.7) # 添加模型
prompt = ChatPromptTemplate.from_template(template)
chain = prompt | model
result = chain.invoke({
"question": "你比GPT4厉害吗?"})
print(result)
在创建链部分,使用管道操作符 |
,它将 prompt 和 model 连接起来,形成一个处理流程。这种链式操作使得我们可以轻松地组合和重用不同的组件。
invoke
方法触发整个处理链,将我们的问题传入模板,然后将格式化后的提示发送给模型进行处理。

2.流式输出
流式输出是一种在生成长文本时逐步返回结果的技术。这种方法有几个重要的优势:
- 提高用户体验:用户可以立即看到部分结果,而不是等待整个响应完成。
- 减少等待时间:对于长回答,用户可以在完整回答生成之前就开始阅读。
- 实时交互:允许在生成过程中进行干预或终止。
在实际应用中,特别是在聊天机器人或实时对话系统中,流式输出几乎是必不可少的。
示例代码如下:
from langchain_ollama import ChatOllama
model = ChatOllama(model="llama3.1", temperature=0.7)
messages = [
("human", "你好呀"),
]
for chunk in model.stream(messages):
print(chunk.content, end='', flush=True)
model.stream()
方法是对 Ollama API 的流式输出接口的封装,它返回一个生成器(generator)对象。当调用 model.stream(messages)
时,会完成以下操作:
- 向 Ollama API 发送请求,开始生成响应。
- API 开始生成文本,但不是等到全部生成完毕才返回,而是一小块一小块地返回。
- 每收到一小块文本,
stream()
方法就会 yield 这个文本块。 flush=True
确保每个片段立即显示,而不是等待缓冲区填满。
3.工具调用
工具调用是 AI 模型与外部函数或 API 交互的能力。这使得模型可以执行复杂的任务,如数学计算、数据查询或外部服务调用。
from langchain_ollama import ChatOllama
def simple_calculator(operation: str, x: float, y: float) -> float:
if operation == "add":
return x + y
elif operation == "subtract":
return x - y
elif operation == "multiply":
return x * y
elif operation == "divide":
if y != 0:
return x / y
else:
raise ValueError("Cannot divide by zero")
else:
raise ValueError("Invalid operation")
# 初始化绑定工具的 ChatOllama 模型
llm = ChatOllama(
model="llama3.1",
temperature=0,
).bind_tools([simple_calculator])
# 使用模型进行工具调用
result = llm.invoke(
"你知道一千万乘二是多少吗?"
)
print("Tool calls:", result.tool_calls)
bind_tools
方法允许我们将自定义函数注册到模型中。这样,当模型遇到需要计算的问题时,它可以调用这个函数来获得准确的结果,而不是依赖于其预训练知识。
这种能力在构建复杂的 AI 应用时非常有用,例如:
- 创建可以访问实时数据的聊天机器人
- 构建能执行特定任务(如预订、查询等)的智能助手
- 开发能进行精确计算或复杂操作的 AI 系统
4.多模态模型调用
Ollama 支持多模态模型,如 bakllava 和 llava。多模态模型是能够处理多种类型输入(如文本、图像、音频等)的 AI 模型。这些模型在理解和生成跨模态内容方面表现出色,使得更复杂和自然的人机交互成为可能。
首先,需要下载多模态模型。在命令行执行:
ollama pull llava
然后通过以下代码实现多模态模型的调用
from langchain_ollama import ChatOllama
from langchain_core.messages import HumanMessage
from langchain_core.output_parsers import StrOutputParser
from PIL import Image
llm = ChatOllama(model="llava", temperature=0)
def convert_to_base64(pil_image):
"""
将 PIL 图像转换为 Base64 编码的字符串
:param pil_image: PIL 图像
:return: 调整大小后的 Base64 字符串
"""
buffered = BytesIO()
pil_image.save(buffered, format="JPEG") # 如果需要,可以更改格式
img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
return img_str
def prompt_func(data):
'''构造多模态输入'''
text = data["text"]
image = data["image"]
image_part = {
"type": "image_url",
"image_url": f"data:image/jpeg;base64,{
image}",
}
content_parts = []
text_part = {
"type": "text", "text": text}
content_parts.append(image_part)
content_parts.append(text_part)
return [HumanMessage(content=content_parts)]
file_path = "./task04/aa.jpg"
pil_image = Image.open(file_path)
image_b64 = convert_to_base64(pil_image)
chain = prompt_func | llm | StrOutputParser()
query_chain = chain.invoke(
{
"text": "这个图片里是什么动物啊?", "image": image_b64}
print(query_chain)
这里的关键点是:
- 图像预处理:我们需要将图像转换为 base64 编码的字符串。
- 提示函数:
prompt_func
创建了一个包含文本和图像的多模态输入。 - 链式处理:我们使用
|
操作符将提示函数、模型和输出解析器连接起来。
四、进阶使用
1.使用 ConversationChain 进行对话
ConversationChain
是 LangChain 提供的一个强大工具,用于管理多轮对话。它结合了语言模型、提示模板和内存组件,使得创建具有上下文感知能力的对话系统变得简单。
完整示例代码如下
from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemory
from langchain_ollama import OllamaLLM
# 初始化Ollama LLM
model_name = "llama3.1"
model = OllamaLLM(model=model_name)
# 初始化 ConversationBufferMemory
memory = ConversationBufferMemory()
# 创建 ConversationChain
conversation = ConversationChain(
llm=model,
memory=memory,
verbose=True
) # 设置 verbose=True 以显示调试信息, 默认为 False
# 进行对话
response = conversation.predict(input="你好,我想了解一下人工智能。")
print("AI:", response)
response = conversation.predict(input="能给我举个AI在日常生活中的应用例子吗?")
print("AI:", response)
response = conversation.predict(input="这听起来很有趣。AI在医疗领域有什么应用?")
print("AI:", response)
这里的关键组件是:
ConversationBufferMemory
:这是一个简单的内存组件,它存储所有先前的对话历史。ConversationChain
:它将语言模型、内存和一个默认的对话提示模板组合在一起。
维护对话历史很重要,因为它允许模型:
- 理解上下文和之前提到的信息
- 生成更连贯和相关的回复
- 处理复杂的多轮对话场景
在实际应用中,你可能需要考虑使用更高级的内存组件,如 ConversationSummaryMemory
,以处理长对话并避免超出模型的上下文长度限制。
输出结果如下所示:
2.自定义提示模板
设计好的提示模板是创建高效 AI 应用的关键。在这个例子中,我们创建了一个用于生成产品描述的复杂提示:
system_message = SystemMessage(content="""
你是一位经验丰富的电商文案撰写专家。你的任务是根据给定的产品信息创作吸引人的商品描述。
请确保你的描述简洁、有力,并且突出产品的核心优势。
""")
human_message_template = """
请为以下产品创作一段吸引人的商品描述:
产品类型: {product_type}
核心特性: {key_feature}
目标受众: {target_audience}
价格区间: {price_range}
品牌定位: {brand_positioning}
请提供以下三种不同风格的描述,每种大约50字:
1. 理性分析型
2. 情感诉求型
3. 故事化营销型
"""
# 示例使用
product_info = {
"product_type": "智能手表",
"key_feature": "心率监测和睡眠分析",
"target_audience": "注重健康的年轻专业人士",
"price_range": "中高端",
"brand_positioning": "科技与健康的完美结合"
}
这个结构有几个重要的设计考虑:
- system_prompt:定义了 AI 的角色和总体任务,设置了整个对话的基调。
- human_message_template:提供了具体的指令和所需信息的结构。
- 多参数设计:允许灵活地适应不同的产品和需求。
- 多样化输出要求:通过要求不同风格的描述,鼓励模型展示其多样性。
设计有效的提示模板时,考虑以下几点:
- 明确定义 AI 的角色和任务
- 提供清晰、结构化的输入格式
- 包含具体的输出要求和格式指导
- 考虑如何最大化模型的能力和创造力
完整示例代码:
from langchain_ollama import ChatOllama
from langchain_core.messages import SystemMessage, HumanMessage
# 初始化ChatOllama模型
model = ChatOllama(model="llama3.1", temperature=0.7)
system_message = SystemMessage(content="""
你是一位经验丰富的电商文案撰写专家。你的任务是根据给定的产品信息创作吸引人的商品描述。
请确保你的描述简洁、有力,并且突出产品的核心优势。
""")
human_message_template = """
请为以下产品创作一段吸引人的商品描述:
产品类型: {product_type}
核心特性: {key_feature}
目标受众: {target_audience}
价格区间: {price_range}
品牌定位: {brand_positioning}
请提供以下三种不同风格的描述,每种大约50字:
1. 理性分析型
2. 情感诉求型
3. 故事化营销型
"""
def generate_product_descriptions(product_info):
human_message = HumanMessage(content=human_message_template.format(**product_info))
messages = [system_message, human_message]
response = model.invoke(messages)
return response.content
# 示例使用
product_info = {
"product_type": "智能手表",
"key_feature": "心率监测和睡眠分析",
"target_audience": "注重健康的年轻专业人士",
"price_range": "中高端",
"brand_positioning": "科技与健康的完美结合"
}
result = generate_product_descriptions(product_info)
print(result)
输出结果如下所示:
$ python task04/ChatOllamaWithTemplate.py
**理性分析型**
"高科技智能手表,让你与健康保持同步。实时心率监测和睡眠分析,为你的健身计划提供科学依据。轻松追踪你的身体变化,实现更好的生活质量。高精度数据为你决策,助你成长为完美版的自己。"
**情感诉求型**
"让健康成为你最大的爱好!与我的智能手表一起,拥抱每个新的日子。实时监测你的心率和睡眠,让你更了解自己的身体,享受生活的快乐。让我们一起追寻健康的理想生活吧!"
**故事化营销型**
"在一次激动人心的远征中,你遇到了自己。有心率监测和睡眠分析的智能手表陪伴着你,每一步都记录在心,体验每个瞬间的纯粹。追寻健康的理想生活,不仅是目标,更是一场不息的冒险。与我一起,开启健康之旅吧!"
3.构建一个简单的 RAG 问答系统
RAG(Retrieval-Augmented Generation)是一种结合了检索和生成的 AI 技术,它通过检索相关信息来增强语言模型的回答能力。RAG 系统的工作流程通常包括以下步骤:
- 将知识库文档分割成小块并创建向量索引
- 对用户的问题进行向量化,在索引中检索相关文档
- 将检索到的相关文档和原始问题一起作为上下文提供给语言模型
- 语言模型根据检索到的信息生成回答
RAG 的优势在于它可以帮助语言模型访问最新和专业的信息,减少幻觉,并提高回答的准确性和相关性。
LangChain 提供了多种组件,可以与 Ollama 模型无缝集成。这里我们将展示如何将 Ollama 模型与向量存储和检索器结合使用,创建一个简单的 RAG 问答系统。
首先需要确保下载 embedding 模型,可以在命令行执行以下命令:
ollama pull nomic-embed-text
完整示例代码如下:
from langchain_ollama import ChatOllama
from langchain_community.vectorstores import FAISS
from langchain_ollama import OllamaEmbeddings
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 初始化 Ollama 模型和嵌入
llm = ChatOllama(model="llama3.1")
embeddings = OllamaEmbeddings(model="nomic-embed-text")
# 准备文档
text = """
Datawhale 是一个专注于数据科学与 AI 领域的开源组织,汇集了众多领域院校和知名企业的优秀学习者,聚合了一群有开源精神和探索精神的团队成员。
Datawhale 以“ for the learner,和学习者一起成长”为愿景,鼓励真实地展现自我、开放包容、互信互助、敢于试错和勇于担当。
同时 Datawhale 用开源的理念去探索开源内容、开源学习和开源方案,赋能人才培养,助力人才成长,建立起人与人,人与知识,人与企业和人与未来的联结。
如果你想在Datawhale开源社区发起一个开源项目,请详细阅读Datawhale开源项目指南[https://github.com/datawhalechina/DOPMC/blob/main/GUIDE.md]
"""
text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=20)
chunks = text_splitter.split_text(text)
# 创建向量存储
vectorstore = FAISS.from_texts(chunks, embeddings)
retriever = vectorstore.as_retriever()
# 创建提示模板
template = """只能使用下列内容回答问题:
{context}
Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
# 创建检索-问答链
chain = (
{
"context": retriever, "question": RunnablePassthrough()}
| prompt
| llm
)
# 使用链回答问题
question = "我想为datawhale贡献该怎么做?"
response = chain.invoke(question)
print(response.content)
这个 RAG 系统的工作原理如下:
- 文本分割:使用
RecursiveCharacterTextSplitter
将长文本分割成小块。 - 向量化和索引:使用
OllamaEmbeddings
将文本块转换为向量,并用 FAISS 创建向量索引。 - 检索:当收到问题时,系统会将问题向量化,并在 FAISS 索引中检索最相关的文本块。
- 生成回答:将检索到的相关文本块与原始问题一起提供给语言模型,生成最终答案。
RAG 系统在许多真实场景中非常有用,例如:
- 客户服务:可以基于公司的知识库快速回答客户询问。
- 研究辅助:帮助研究人员快速找到相关文献并总结关键信息。
- 个人助手:结合个人笔记和网络信息,提供个性化的信息检索和建议。
五、遇到问题与解决
1.numpy版本冲突
报错日志如下
A module that was compiled using NumPy 1.x cannot be run in
NumPy 2.2.3 as it may crash. To support both 1.x and 2.x
versions of NumPy, modules must be compiled with NumPy 2.0.
Some module may need to rebuild instead e.g. with 'pybind11>=2.12'.
If you are a user of the module, the easiest solution will be to
downgrade to 'numpy<2' or try to upgrade the affected module.
We expect that some modules will need time to support NumPy 2.
Traceback (most recent call last): File "/home/allyoung/task04/ChatOllamaRAG.py", line 24, in <module>
vectorstore = FAISS.from_texts(chunks, embeddings)
File "/home/allyoung/anaconda3/envs/deepseek/lib/python3.10/site-packages/langchain_community/vectorstores/faiss.py", line 1044, in from_texts
return cls.__from(
File "/home/allyoung/anaconda3/envs/deepseek/lib/python3.10/site-packages/langchain_community/vectorstores/faiss.py", line 996, in __from
faiss = dependable_faiss_import()
File "/home/allyoung/anaconda3/envs/deepseek/lib/python3.10/site-packages/langchain_community/vectorstores/faiss.py", line 56, in dependable_faiss_import
import faiss
File "/home/allyoung/anaconda3/envs/deepseek/lib/python3.10/site-packages/faiss/__init__.py", line 18, in <module>
from .loader import *
File "/home/allyoung/anaconda3/envs/deepseek/lib/python3.10/site-packages/faiss/loader.py", line 65, in <module>
from .swigfaiss import *
File "/home/allyoung/anaconda3/envs/deepseek/lib/python3.10/site-packages/faiss/swigfaiss.py", line 13, in <module>
from . import _swigfaiss
AttributeError: _ARRAY_API not found
Traceback (most recent call last):
File "/home/allyoung/anaconda3/envs/deepseek/lib/python3.10/site-packages/langchain_community/vectorstores/faiss.py", line 56, in dependable_faiss_import
import faiss
File "/home/allyoung/anaconda3/envs/deepseek/lib/python3.10/site-packages/faiss/__init__.py", line 18, in <module>
from .loader import *
File "/home/allyoung/anaconda3/envs/deepseek/lib/python3.10/site-packages/faiss/loader.py", line 65, in <module>
from .swigfaiss import *
File "/home/allyoung/anaconda3/envs/deepseek/lib/python3.10/site-packages/faiss/swigfaiss.py", line 13, in <module>
from . import _swigfaiss
ImportError: numpy.core.multiarray failed to import
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/allyoung/task04/ChatOllamaRAG.py", line 24, in <module>
vectorstore = FAISS.from_texts(chunks, embeddings)
File "/home/allyoung/anaconda3/envs/deepseek/lib/python3.10/site-packages/langchain_community/vectorstores/faiss.py", line 1044, in from_texts
return cls.__from(
File "/home/allyoung/anaconda3/envs/deepseek/lib/python3.10/site-packages/langchain_community/vectorstores/faiss.py", line 996, in __from
faiss = dependable_faiss_import()
File "/home/allyoung/anaconda3/envs/deepseek/lib/python3.10/site-packages/langchain_community/vectorstores/faiss.py", line 58, in dependable_faiss_import
raise ImportError(
ImportError: Could not import faiss python package. Please install it with `pip install faiss-gpu` (for CUDA supported GPU) or `pip install faiss-cpu` (depending on Python version).
解决方式:
$ pip uninstall numpy
$ pip install numpy==1.26.4 -i https://pypi.tuna.tsinghua.edu.cn/simple
六、推荐链接:
https://github.com/wdndev/llm_interview_note/blob/main/10.大语言模型应用/1.langchain/1.langchain.md