LangChain + Ollama + DeepSeek 全链路认知:从模型包装器到提示词模版 Agent Demo

举报
山河已无恙 发表于 2025/03/13 13:01:27 2025/03/13
【摘要】 写在前面博文内容为 LangChain + Ollama + DeepSeek 本地部署 LLM 应用开发认知涉及 LangChain 架构,核心模块认知以及 模型包装器,提示词模版,Agent 方式开发AI应用 Demo理解不足小伙伴帮忙指正 :),生活加油 我看远山,远山悲悯持续分享技术干货,感兴趣小伙伴可以关注下 ^_^ lang Chain 基本认知在开源项目中,它这样介绍自己:L...

写在前面


  • 博文内容为 LangChain + Ollama + DeepSeek 本地部署 LLM 应用开发认知
  • 涉及 LangChain 架构,核心模块认知
  • 以及 模型包装器,提示词模版,Agent 方式开发AI应用 Demo
  • 理解不足小伙伴帮忙指正 :),生活加油

我看远山,远山悲悯

持续分享技术干货,感兴趣小伙伴可以关注下 ^_^


lang Chain 基本认知

在开源项目中,它这样介绍自己:

LangChain 是一个用于开发由大型语言模型(LLMs)驱动的应用程序的框架。对于这些应用,LangChain 简化了整个应用生命周期:

  • 开源库: 使用 LangChain 的开源组件和第三方集成构建您的应用程序。使用 LangGraph 构建具有流处理和人机交互支持带状态代理
  • 生产化: 使用 LangSmith 检查、监控和评估您的应用程序,以便您可以不断进行优化并充满信心地进行部署。
  • 部署: 使用 LangGraph 平台将您的 LangGraph 应用程序转换为生产就绪的API助手。LangGraph是一个用于构建具有LLMs的状态和多主体应用程序的库,用于创建代理和多代理工作流。

对应的项目地址:

这里我们只关注 langchainlanggraphlangsmith 在之后的博文和小伙伴分享

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)

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。