LangChain + Ollama + DeepSeek 全链路认知:从模型包装器到提示词模版 Agent Demo
写在前面
- 博文内容为
LangChain
+Ollama
+DeepSeek
本地部署 LLM 应用开发认知 - 涉及
LangChain
架构,核心模块认知 - 以及 模型包装器,提示词模版,
Agent
方式开发AI应用Demo
- 理解不足小伙伴帮忙指正 :),生活加油
我看远山,远山悲悯
持续分享技术干货,感兴趣小伙伴可以关注下 ^_^
lang Chain 基本认知
在开源项目中,它这样介绍自己:
LangChain
是一个用于开发由大型语言模型(LLMs)驱动的应用程序的框架
。对于这些应用,LangChain
简化了整个应用生命周期:
开源库
: 使用LangChain
的开源组件和第三方集成构建您的应用程序。使用LangGraph
构建具有流处理和人机交互支持
的带状态代理
。生产化
: 使用LangSmith
检查、监控和评估您的应用程序,以便您可以不断进行优化并充满信心地进行部署。部署
: 使用LangGraph
平台将您的LangGraph
应用程序转换为生产就绪的API
和助手
。LangGraph是一个用于构建具有LLMs的状态和多主体应用程序的库,用于创建代理和多代理工作流。
对应的项目地址:
- langchain: https://github.com/langchain-ai/langchain
- langgraph: https://github.com/langchain-ai/langgraph
- langsmith: https://github.com/langchain-ai/langsmith-sdk
这里我们只关注 langchain
,langgraph
和 langsmith
在之后的博文和小伙伴分享
Lang Chain
应用场景: 问答系统,数据处理与管理,Agent
,RAG
等
lang Chain 架构
lang Chain
通过 组件
和链
提供基础能力,类似我们常常画的流程图,工作流引擎一样。
组件: 组件是一个具有明确功能和用途的单元
。 类似流程图中的处理框,组件包括提示工程模版
, LLM模型包装器
、聊天模型包装器
等以及和数据增强相关
的一系列工具和接口
。可以把它们看作数据处理流水线上的各个工作站。每个组件都有其特定的职责,如处理数据的输入输出、转化数据格式。
链: 链是将各种组件连接在一起,它确保组件之间的无缝集成和在程序运行环境中的高效调用。
Lang Chain 核心模块
1.模型 I/O(Model IO)
LangChain 提供了与任何大语言模型均适配的模型包装器(
模型 I/0 的功能)分为 模型包装器(LLM)
和聊天模型包装器(Chat Model)
。
LangChain 自身并不提供大语言模型而是提供统一的模型接口。模型包装器这种包装方式允许开发者与不同模型平台底层的 API进行交互
,从而简化了大语言模型的调用,降低了开发者的学习成本。此外,其输出解析器也能帮助开发者从模型输出中提取所需的信息。
模型包装器
的提示词模板
功能使得开发者可以模板化、动态选择和管理模型输人
2.数据增强(Data Connection)
许多LLM 应用需要的用户特定数据并不在模型的训练集中。LangChain 提供了加载、转换、存储和査询数据的构建块
。开发者可以利用文档加载器
从多个来源加载文档
,通过文档转换器进行文档切割、转换等操作。矢量存储和数据检索工具则提供了对嵌人数据的存储和查询功能。
3.链( Chain)
单独使用LLM 对于简单应用可能是足够的,但面对复杂的应用往往需要将多个 LLM 模型包装器或其他组件进行链式连接
。LangChain 为此类链式应用提供了接口。 有点类似于设计模式中的构建者,按需 build ,每次都返回实例本身
4.记忆(Memory)
LangChain 提供了多种工具帮助开发者为系统添加记忆功能
。记忆功能可以独立使用,也可以无缝集成到链中。记忆模块需要支持两个基本操作,即读取和写入
。
在每次运行中,链首先从记忆模块中读取数据,然后在执行核心逻辑后将当前运行的输人和输出写入记忆模块,以供未来引用。通俗的讲,就是会申请一块内存存房历史会话数据。
5.Agent
核心思想是利用LLM 选择操作序列
。即把之后的组件调用的决策权交给 LLM,在链中,操作序列
是硬编码
的,而在代理(Agent)代理中,大语言模型被用作推理引擎
,确定执行哪些操作,以及它们的执行顺序。
6.回调处理器(Callback)
LangChain
提供了一个回调系统,允许开发者在LLM应用的各个阶段对状态进行干预。这对于日志记录、监视、流处理等任务非常有用。通过API提供的回调参数,开发者可以订阅这些事件。
Demo 实战
理论学了那么多,我看几个简单的Demo 认识一下。
我们通过 Ollama
在本地部署 DeepSeek-R1
蒸馏模型,通过 langChain
调用
下载模型,启动 Ollama
服务
PS C:\Users\Administrator> ollama list
NAME ID SIZE MODIFIED
deepseek-r1:latest 0a8c26691023 4.7 GB 3 seconds ago
deepseek-r1:32b 38056bbcbb2d 19 GB 2 weeks ago
deepseek-r1:14b ea35dfe18182 9.0 GB 2 weeks ago
deepseek-r1:8b 28f8fd6cdc67 4.9 GB 2 weeks ago
bge-m3:latest 790764642607 1.2 GB 2 weeks ago
PS C:\Users\Administrator> ollama serve
Error: listen tcp 127.0.0.1:11434: bind: Only one usage of each socket address (protocol/network address/port) is normally permitted.
PS C:\Users\Administrator> ollama serve
2025/03/09 01:22:39 routes.go:1187: INFO server config env="map[CUDA_VISIBLE_DEVICES: GPU_DEVICE_ORDINAL: HIP_VISIBLE_DEVICES: HSA_OVERRIDE_GFX_VERSION: HTTPS_PROXY: HTTP_PROXY: NO_PROXY: OLLAMA_DEBUG:false OLLAMA_FLASH_ATTENTION:false OLLAMA_GPU_OVERHEAD:0 OLLAMA_HOST:http://127.0.0.1:11434 OLLAMA_INTEL_GPU:false OLLAMA_KEEP_ALIVE:5m0s OLLAMA_KV_CACHE_TYPE: OLLAMA_LLM_LIBRARY: OLLAMA_LOAD_TIMEOUT:5m0s OLLAMA_MAX_LOADED_MODELS:0 OLLAMA_MAX_QUEUE:512 OLLAMA_MODELS:C:\\Users\\Administrator\\.ollama\\models OLLAMA_MULTIUSER_CACHE:false OLLAMA_NOHISTORY:false OLLAMA_NOPRUNE:false OLLAMA_NUM_PARALLEL:0 OLLAMA_ORIGINS:[http://localhost https://localhost http://localhost:* https://localhost:* http://127.0.0.1 https://127.0.0.1 http://127.0.0.1:* https://127.0.0.1:* http://0.0.0.0 https://0.0.0.0 http://0.0.0.0:* https://0.0.0.0:* app://* file://* tauri://* vscode-webview://*] OLLAMA_SCHED_SPREAD:false ROCR_VISIBLE_DEVICES:]"
time=2025-03-09T01:22:39.303+08:00 level=INFO source=images.go:432 msg="total blobs: 14"
time=2025-03-09T01:22:39.304+08:00 level=INFO source=images.go:439 msg="total unused blobs removed: 0"
time=2025-03-09T01:22:39.306+08:00 level=INFO source=routes.go:1238 msg="Listening on 127.0.0.1:11434 (version 0.5.7)"
time=2025-03-09T01:22:39.306+08:00 level=INFO source=routes.go:1267 msg="Dynamic LLM libraries" runners="[cuda_v12_avx rocm_avx cpu cpu_avx cpu_avx2 cuda_v11_avx]"
time=2025-03-09T01:22:39.306+08:00 level=INFO source=gpu.go:226 msg="looking for compatible GPUs"
time=2025-03-09T01:22:39.306+08:00 level=INFO source=gpu_windows.go:167 msg=packages count=1
time=2025-03-09T01:22:39.308+08:00 level=INFO source=gpu_windows.go:183 msg="efficiency cores detected" maxEfficiencyClass=1
time=2025-03-09T01:22:39.308+08:00 level=INFO source=gpu_windows.go:214 msg="" package=0 cores=12 efficiency=4 threads=20
time=2025-03-09T01:22:39.448+08:00 level=INFO source=types.go:131 msg="inference compute" id=GPU-e65029a6-c2f9-44b1-bd76-c12e4083fa4c library=cuda variant=v12 compute=8.6 driver=12.8 name="NVIDIA GeForce RTX 3060" total="12.0 GiB" available="11.0 GiB"
LLMs 模型包装器
下面为一个 基本的 Demo,使用 llm 模型包装器,进行预测推理,
- invoke 是一个通用方法,用于同步调用模型、工具或组件的主要功能。它的核心作用是向目标对象传递输入数据并获取输出结果。
- stream 是 LangChain 等大语言模型(LLM)框架中用于
流式逐块生成文本
的核心方法。它的核心作用是:实时获取模型输出的片段(chunk)
,适用于需要逐步展示生成内容、降低延迟感知或处理长文本的场景。
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
@File : demo.py
@Time : 2025/03/09 01:13:15
@Author : Li Ruilong
@Version : 1.0
@Contact : liruilonger@gmail.com
@Desc : LangChain Demo
"""
# here put the import lib
#pip install langchain langchain-community ollama -i https://pypi.tuna.tsinghua.edu.cn/simple
from langchain_community.llms import Ollama
# 初始化 Ollama 连接
llm = Ollama(
base_url="http://localhost:11434", # Ollama 默认端口
model="deepseek-r1:latest",
temperature=0.3, # 控制创造性(0-1)
num_ctx=4096 # 上下文长度
)
# 单次对话
response = llm.invoke("LLM 是什么?")
print("回答:", response)
print("===========================================================")
# 流式输出(适合长文本)
for chunk in llm.stream("LLM 如何学习?"):
print(chunk, end="", flush=True)
下面为 invoke 输出结果
LLM 是 "Large Language Model" 的缩写,即大型语言模型。这类模型由深度学习驱动,能够模拟人类-like 思维过程,并且能够生成和理解自然语言文本。
### 主要特点
1. **复杂性**:通常包含数百亿参数。
2. **规模**:参数数量多,计算资源要求高。
3. **训练数据**:依赖海量文本数据进行微调或预训练。
4. **任务**:包括文本生成、问答、翻译等。
.....................
prompts 提示词模版
提示词模板 这里使用 PromptTemplate
模块,这是一个最基本的实现,下面Demo 中
# 创建提示模板
prompt = PromptTemplate(
input_variables=["topic"],
template="用中文写一首关于 {topic} 的五言绝句:"
)
input_variables
用于定义变量参数,template
用于定义模版
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
@File : demo copy 2.py
@Time : 2025/03/09 03:19:59
@Author : Li Ruilong
@Version : 1.0
@Contact : liruilonger@gmail.com
@Desc : None
"""
# here put the import lib
# here put the import lib
#pip install langchain langchain-community ollama -i https://pypi.tuna.tsinghua.edu.cn/simple
from langchain.chains import LLMChain
from langchain_community.llms import Ollama
from langchain_core.prompts import PromptTemplate
# 初始化模型
llm = Ollama(model="deepseek-r1")
# 创建提示模板
prompt = PromptTemplate(
input_variables=["topic"],
template="用中文写一首关于 {topic} 的五言绝句:"
)
# 构建 Chain
chain = LLMChain(llm=llm, prompt=prompt)
# 执行调用
print(chain.run("秋天的枫叶"))
输出结果
<think>
好的,用户让我用中文写一首关于秋天枫叶的五言绝句。首先,我得理解用户的需求,他们可能想表达对秋天的赞美或者怀念。五言绝句结构紧凑,每句五个字,押韵,所以需要 简洁有力。
接下来,考虑秋天枫叶的特点:红叶、萧瑟、自然的变化。想到枫叶的颜色变化,红叶象征着成熟和热情。我需要用一些生动的词语来描绘枫叶的状态,比如“染”、“飞舞”等。
然后,考虑整体意境。秋天不仅是季节变换,还有一种宁静或深远的感觉。可能加入一些自然元素,如山色、风霜,来增强画面感。
结构上,四句每句五个字,押韵。首句点明主题,中间两句描绘景象,末句升华主题。比如:
第一句:“红叶正秋染”,引出季节和颜色变化。
第二句:“山色起风霜”,描绘环境的变化和寒意。
第三句:“一片飞舞地”,形容红叶的状态。
第四句:“满城换新装”,表现秋天带来的变化。
这样组合起来,整首诗既有画面感,又表达了对秋天的热爱。最后检查押韵是否合适,确保每句末尾字的平仄和谐。
总的来说,这首诗通过描绘红叶的颜色和动态,以及整体环境的变化,传达出秋天的美丽和成熟。
</think>
《题陶山枫》
红叶正秋染,山色起风霜。
一片飞舞地,满城换新装。
PS C:\Users\Administrator\Documents\GitHub\LangChainDemo>
Agent Demo
相对于于传统的方式,Agent 提供了记忆功能和决策功能
我们先来看一个记忆功能的 Demo
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
@File : demo_memory.py
@Time : 2025/03/09 03:21:59
@Author : Li Ruilong
@Version : 1.0
@Contact : liruilonger@gmail.com
@Desc : None
"""
# here put the import lib
# here put the import lib
#pip install langchain langchain-community ollama -i https://pypi.tuna.tsinghua.edu.cn/simple
from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferWindowMemory
from langchain_community.llms import Ollama
llm = Ollama(model="deepseek-r1")
# 保留最近3轮对话历史
memory = ConversationBufferWindowMemory(k=3)
conversation = ConversationChain(llm=llm, memory=memory)
# 多轮对话示例
print(conversation.run("帮我写一个斐波那契数列的Python函数"))
print(conversation.run("添加类型注解"))
print(conversation.run("优化时间复杂度"))
下面为 Agent 的输出
<think>
嗯,用户想让我帮他写一个斐波那契数列的Python函数。首先,我需要确认他具体想要什么样的斐波那契数列。常见的有两种版本:一种是从第0项开始,另一种是从第1项开始。
............
<think>
当然!让我为您添加类型注解到斐波那契数列函数中。以下是带有具体类型的Python函数:
..............................
<think>
嗯,用户想让我帮他优化斐波那契数列函数的时间复杂度。首先,我需要了解当前的实现方法是什么样的。之前的回复提供了一个迭代版本,时间复杂度是O(n),这对大多数用途 来说已经足够高效了。
...................
下面为一个带记忆和决策功能的 Agent Demo
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
@File : demo_agent.py
@Time : 2025/03/09 03:46:56
@Author : Li Ruilong
@Version : 1.0
@Contact : liruilonger@gmail.com
@Desc : None
"""
# here put the import lib
# here put the import lib
from langchain_community.llms import Ollama
from langchain_community.chat_models import ChatOllama
from langchain.agents import AgentType, initialize_agent, Tool
from langchain.memory import ConversationBufferWindowMemory
from langchain_community.tools import WikipediaQueryRun
from langchain_community.utilities import WikipediaAPIWrapper
# 自定义文学分析工具(无需API)
class BookQuotesTool:
@staticmethod
def search_quotes(book_title: str, author: str = "木心") -> str:
"""模拟文学语录检索(实际可接入本地知识库)"""
quotes_db = {
"素履之往": [
"生命好在无意义,才容得下各自赋予意义。",
"所谓无底深渊,下去,也是前程万里。",
"岁月不饶人,我亦未曾饶过岁月。"
]
}
return "\n".join(quotes_db.get(book_title, ["暂未收录该作品语录"]))
# 配置本地模型
llm = Ollama(model="deepseek-r1:latest", temperature=0.3)
chat_model = ChatOllama(model="deepseek-r1:latest")
# 初始化记忆系统
memory = ConversationBufferWindowMemory(
memory_key="chat_history",
k=5,
return_messages=True
)
# 构建定制化工具集
tools = [
Tool(
name="LiteratureSearch",
func=lambda query: BookQuotesTool.search_quotes("素履之往"),
description="用于检索木心《素履之往》的经典语录"
),
WikipediaQueryRun(
api_wrapper=WikipediaAPIWrapper(top_k_results=1, lang="zh")
)
]
# 创建带文学分析能力的Agent
agent = initialize_agent(
tools,
chat_model,
agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION,
memory=memory,
verbose=True,
handle_parsing_errors=True,
max_iterations=3 # 限制搜索深度
)
# 测试用例
queries = [
"列举《素履之往》中关于时间的哲理语句",
"这本书里如何阐述生命的意义?",
"将第二句语录用英文翻译"
]
for q in queries:
print(f"问题:{q}")
print(agent.run(q))
print("\n" + "="*50 + "\n")
下面为输出结构,我们可以看到 第一个到第二个问题,体现记忆功能,第二个问题,到第三个问题是由第二个问题的输出,决策第三个问题的答案。
问题:列举《素履之往》中关于时间的哲理语句
C:\Users\Administrator\Documents\GitHub\LangChainDemo\demo\demo_agent.py:78: LangChainDeprecationWarning: The method `Chain.run` was deprecated in langchain 0.1.0 and will be removed in 1.0. Use :meth:`~invoke` instead.
print(agent.run(q))
> Entering new AgentExecutor chain...
<think>
好,我现在要回答用户的问题:“列举《素履之往》中关于时间的哲理语句”。首先,我需要理解用户的需求。他们想要找到《素履之往》中的时间相关的哲理句子。
接下来,我会回想一下《素履之往》的内容。这是一部哲学著作,主要讨论生活态度和处世之道。作者在这本书中强调的是内心修持的重要性,而时间并不是特别受重视的一方面 。因此,我需要确认是否有关于时间的直接论述。
如果找不到直接提到时间的句子,我可以考虑其他方法。例如,通过分析作者的观点来间接理解他对时间的看法。但通常情况下,这种书更注重内在修养而非时间管理或哲学中的 时间概念。
综上所述,可能《素履之往》中并没有专门讨论时间的哲理句子。因此,我应该建议用户如果没有找到相关的内容,可以尝试查阅相关的注释或学术评论,了解是否有学者对其中 的时间主题有解读。
</think>
> Finished chain.
由于《素履之往》主要关注的是人的日常生活态度和处世之道,而时间并不是其核心讨论的主题,因此可以推测书中并未专门列出关于时间的哲理语句。为了更全面地了解,您可 以查阅相关注释或学术评论以获取对时间主题的解读。
==================================================
问题:这本书里如何阐述生命的意义?
> Entering new AgentExecutor chain...
<think>
好的,现在我要分析用户的问题:“这本书里如何阐述生命的意义?” 用户提到的是《素履之往》,而我之前已经告诉过他们,这本书主要讨论的是处世态度和生活态度,并没有专门探讨时间或其他主题的哲理语句。所以,我应该建议他们查阅相关的注释或学术评论来了解书中关于生命意义的内容。
接下来,用户要求列举关于时间的哲理语句,但由于《素履之往》并没有涉及时间主题,所以最好的办法是引导他们去寻找相关资料。我需要提醒用户,如果他们想了解更多关于 生命的意义,可以参考其他资源,比如注释、评论或学术研究。
最后,按照指示,我应该输出一个JSON格式的指令,告诉用户使用文学搜索工具来查找相关的语录。这样他们就能找到更多的信息了。
</think>
{
"action": "LiteratureSearch",
"action_input": "《素履之往》中关于生命意义的经典语录有哪些?"
}
Observation: 生命好在无意义,才容得下各自赋予意义。
所谓无底深渊,下去,也是前程万里。
岁月不饶人,我亦未曾饶过岁月。
Thought:<think>
...............................
> Finished chain.
==================================================
问题:将第二句语录用英文翻译
> Entering new AgentExecutor chain...
<think>
Alright, I need to help the user translate the second sentence of "素履之往" into English. First, let me recall what that sentence is about.
From what I remember, the second sentence translates something like "The journey of life is best traveled alone." That's a pretty common translation, so it makes sense if it's from this book.
Now, to make sure I'm accurate, I'll think through why that would be an appropriate translation. The wording in Chinese emphasizes independence and personal experience, which aligns with the English phrase about traveling alone for growth.
I should also consider if there are any nuances or alternative translations suggested by experts, but from what I know, this is a widely accepted version.
</think>
{
"action": "Final Answer",
"action_input": "The journey of life is best traveled alone."
}
> Finished chain.
The journey of life is best traveled alone.
==================================================
PS C:\Users\Administrator\Documents\GitHub\LangChainDemo>
Lang Chain 表达式
类似 Linux
中的管道操作,LangChain
中也可以通过管道符链接组构成一些常见表达式。比如 提示词模板+模型包装器
,提示词模板+模型包装器+输出解析器
下面是一个 基础 Demo
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
@File : demo_prompts.py
@Time : 2025/03/09 03:17:01
@Author : Li Ruilong
@Version : 1.0
@Contact : liruilonger@gmail.com
@Desc : None
"""
# here put the import lib
#pip install langchain langchain-community ollama -i https://pypi.tuna.tsinghua.edu.cn/simple
from langchain_community.llms import Ollama
from langchain.prompts import ChatPromptTemplate
# 初始化 Ollama 连接
llm = Ollama(
base_url="http://localhost:11434", # Ollama 默认端口
model="deepseek-r1:latest",
temperature=0.3, # 控制创造性(0-1)
num_ctx=4096 # 上下文长度
)
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个Linux 性能调优专家,现在请回答客户的问题"),
("human", "{input}")
])
chain = prompt | llm
print(chain.invoke({"input": "CPU 使用率 100% 如何排查?"}))
<think>
嗯,用户说他的CPU使用率一直显示100%,这可能是个问题。首先,我得考虑一下是不是系统出现了死循环或者进程卡住了。比如,后台运行了很多程序,特别是那些长时间运行的脚本或服务,可能会占用大量的CPU资源。
.....................................
总之,要排查CPU使用率100%的问题,需要从系统资源、进程行为、磁盘I/O以及软件配置等多个方面进行全面检查,逐步缩小范围找到具体原因。
</think>
如果您的系统显示CPU使用率为100%,这通常意味着系统的资源被耗尽或存在一些问题。以下是一些可能的原因和排查步骤:
### 1. **检查进程占用**
- 使用命令 `top` 或 `htop` 查看当前运行的进程,确认是否有进程长时间运行或占用大量CPU资源。
```bash
top
```
- 如果发现某个进程的CPU使用率持续在100%,可能是该进程存在问题。
。。。。。。。。。。。。。。。。。。
博文部分内容参考
© 文中涉及参考链接内容版权归原作者所有,如有侵权请告知 :)
《LangChain 入门指南构建高可复用、可扩展的 LLM 应用程序》
© 2018-至今, 保持署名-非商用-相同方式共享(CC BY-NC-SA 4.0)
- 点赞
- 收藏
- 关注作者
评论(0)