langchain初探(基于deepseek构建)
# 本文是由jupyter直接导出的,简单列一下用法:
pip install jupyter # Install first
jupyter notebook # 运行jupyter 执行命令之后,在终端中将会显示一系列notebook的服务器信息,同时浏览器将会自动启动Jupyter Notebook。
# 里面的代码后都跟有运行结果,这是jupyter的特色
这是一份langchain的实现笔记,基于deepseek构建的简单Agent,供大家参考。
参考文档:https://python.langchain.ac.cn/docs/integrations/chat/deepseek/ 我的deepseek api_key:sk-8004f0b5f71947d9845eaf3f99e7c62a,里面充值了20元,大家有需要可以免费练习使用,但是不要浪费哦。
1.基本使用
# 导入deepseek api-key
import getpass
import os
if not os.getenv("DEEPSEEK_API_KEY"):
os.environ["DEEPSEEK_API_KEY"] = getpass.getpass("Enter your DeepSeek API key: ")
# 创建大模型
from langchain_deepseek import ChatDeepSeek
llm = ChatDeepSeek(
model="deepseek-chat",
temperature=0,
max_tokens=None,
timeout=None,
max_retries=2, # 最大重试次数
# other params...
)
# 询问大模型
messages = [
(
"system",
"你是一个编程高手,能够很好解决我询问的问题。",
),
("human", "你是谁?你能帮我干什么?"),
]
ai_msg = llm.invoke(messages) # 全部答案生成后才会输出
print(ai_msg)
AIMessage(content='你好!我是DeepSeek,由深度求索公司创造的AI助手。😊\n\n我能帮你做很多事情:\n\n**📝 文字处理类**\n- 写作协助:文章、邮件、报告、创意文案等\n- 翻译各种语言\n- 文本总结、分析和改写\n\n**💻 编程技术类**\n- 代码编写、调试和优化\n- 算法解释和实现\n- 技术问题解答\n\n**🎓 学习辅导类**\n- 各学科知识解答\n- 概念解释和举例\n- 学习计划制定\n\n**📊 数据分析类**\n- 处理Excel、PDF、Word等文件\n- 数据整理和分析\n- 图表建议\n\n**🔍 信息查询类**\n- 事实核查\n- 研究协助\n- 方案建议\n\n**🎨 创意类**\n- 头脑风暴\n- 创意策划\n- 故事创作\n\n我有128K的上下文长度,支持文件上传功能,而且完全免费!有什么具体需要帮助的吗?我很乐意为你效劳!✨', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 222, 'prompt_tokens': 22, 'total_tokens': 244, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, 'prompt_cache_hit_tokens': 0, 'prompt_cache_miss_tokens': 22}, 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_ffc7281d48_prod0820_fp8_kvcache', 'id': '480fe421-d6ce-4a77-99d6-4fdf17e8efac', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--f8b71106-af74-4541-8f2b-e289640a7cc1-0', usage_metadata={'input_tokens': 22, 'output_tokens': 222, 'total_tokens': 244, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}})
1.1 流式输出
for chunk in llm.stream(messages): # 流式输出,边生成边输出
print(chunk.text(), end="")
你好!我是DeepSeek,一个由深度求索公司开发的AI助手。😊
我能帮你做很多事情:
**📝 文字处理类**
- 写作协助:文章、邮件、报告、创意文案等
- 翻译各种语言
- 文本总结、分析和改写
**💻 编程技术类**
- 代码编写、调试和优化
- 算法解释和实现
- 技术问题解答
**🎓 学习辅导类**
- 知识答疑解惑
- 学习计划制定
- 概念讲解和举例
**📊 数据分析类**
- 处理Excel、PDF、Word等文件
- 数据整理和分析
- 图表建议和解读
**🔍 信息查询类**
- 事实核查
- 研究协助
- 最新信息搜索(需要你手动开启联网功能)
**🎨 创意类**
- 头脑风暴
- 创意策划
- 问题解决方案
我有128K的上下文长度,可以处理较长的对话和文档。最重要的是,我完全免费!有什么具体需要帮助的吗?我很乐意为你效劳!✨
2.链式调用:将模型与提示模板链式连接起来
from langchain_core.prompts import ChatPromptTemplate
# 提示词模板
prompt = ChatPromptTemplate(
[
(
"system",
"You are a helpful assistant that translates {input_language} to {output_language}.",
),
("human", "{input}"),
]
)
# 构建链条
chain = prompt | llm
chain.invoke(
{
"input_language": "English",
"output_language": "中文",
"input": "I love programming.",
}
)
AIMessage(content='我热爱编程。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 4, 'prompt_tokens': 20, 'total_tokens': 24, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, 'prompt_cache_hit_tokens': 0, 'prompt_cache_miss_tokens': 20}, 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_ffc7281d48_prod0820_fp8_kvcache', 'id': '27863eeb-dfa4-41ee-8a65-60772fdae675', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--d4aa8414-8b3b-4d67-901e-36412130cd0b-0', usage_metadata={'input_tokens': 20, 'output_tokens': 4, 'total_tokens': 24, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}})
2.1 继续构建更加复杂的链
analysis_prompt = ChatPromptTemplate.from_template(
"我应该怎么回答这句话?{talk},给我一个5个字以内的示例"
)
chain2 = {"talk": chain} | analysis_prompt | llm
chain2.invoke(
{
"input_language": "English",
"output_language": "中文",
"input": "I love programming.",
}
)
AIMessage(content='“编程很有趣”', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 4, 'prompt_tokens': 289, 'total_tokens': 293, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 128}, 'prompt_cache_hit_tokens': 128, 'prompt_cache_miss_tokens': 161}, 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_ffc7281d48_prod0820_fp8_kvcache', 'id': '3a2ecd7b-295a-40cf-8134-f82030b93f2a', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--047cb551-c239-4cf3-9878-ead38e4a6805-0', usage_metadata={'input_tokens': 289, 'output_tokens': 4, 'total_tokens': 293, 'input_token_details': {'cache_read': 128}, 'output_token_details': {}})
2.2 构建并行链
from langchain_core.runnables import RunnableParallel
# 提示词模板
prompt_A = ChatPromptTemplate(
[
(
"system",
"You are a helpful assistant that translates chinese to english.",
),
("human", "{input}"),
]
)
prompt_B = ChatPromptTemplate(
[
(
"system",
"You are a helpful assistant that translates Chinese to Japanse.",
),
("human", "{input}"),
]
)
# 构建链:
chain_en = prompt_A | llm
chain_ja = prompt_B | llm
# 并行执行两个链
parallel_chains = RunnableParallel(toEn=chain_en,toJa=chain_ja)
parallel_chains.invoke({"input":"人工智能正在改变世界"})
{'toEn': AIMessage(content='Artificial intelligence is transforming the world.', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 7, 'prompt_tokens': 20, 'total_tokens': 27, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, 'prompt_cache_hit_tokens': 0, 'prompt_cache_miss_tokens': 20}, 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_ffc7281d48_prod0820_fp8_kvcache', 'id': '9cabe7b4-3ff3-423f-8c68-6a373fb5d725', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--68386a17-2938-47a1-a1ac-3159b5d6ecad-0', usage_metadata={'input_tokens': 20, 'output_tokens': 7, 'total_tokens': 27, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}),
'toJa': AIMessage(content='人工知能が世界を変えています。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 10, 'prompt_tokens': 20, 'total_tokens': 30, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, 'prompt_cache_hit_tokens': 0, 'prompt_cache_miss_tokens': 20}, 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_ffc7281d48_prod0820_fp8_kvcache', 'id': '2b07c58d-c6bf-487d-b4d8-26b79230d8da', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--9f5250c6-c2e4-40f8-a353-37e4d7aae473-0', usage_metadata={'input_tokens': 20, 'output_tokens': 10, 'total_tokens': 30, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}})}
2.3 图形化显示链关系
# 图形化显示链条的关系
pip install grandalf
pip install langgraph
parallel_chains.get_graph().print_ascii()
+--------------------------+
| Parallel<toEn,toJa>Input |
+--------------------------+
**** ****
*** ***
** **
+--------------------+ +--------------------+
| ChatPromptTemplate | | ChatPromptTemplate |
+--------------------+ +--------------------+
* *
* *
* *
+--------------+ +--------------+
| ChatDeepSeek | | ChatDeepSeek |
+--------------+ +--------------+
**** ****
*** ***
** **
+---------------------------+
| Parallel<toEn,toJa>Output |
+---------------------------+
3.使用mogodb来保存对话记录,达到连续对话的效果
链接:https://python.langchain.com/docs/integrations/memory/mongodb_chat_message_history/ 安装包:pip install langchain-mongodb 本地下载mongodb后,控制台输入mongod启动,默认端口27017
from langchain_mongodb.chat_message_histories import MongoDBChatMessageHistory
chat_message_history = MongoDBChatMessageHistory(
session_id="test_session", # 会话 ID - 会话的唯一标识符,例如用户名、电子邮件、聊天 ID 等。
connection_string="mongodb://localhost:27017/", # 连接字符串 - 指定数据库连接的字符串。它将被传递给 MongoDB 的 create_engine 函数。
database_name="my_db", # 数据库名 - 要使用的数据库的名称
collection_name="chat_histories", # 集合名 - 在该数据库中使用的集合
)
chat_message_history.add_user_message("Hello")
chat_message_history.add_ai_message("Hi")
print(chat_message_history.messages)
[HumanMessage(content='Hello', additional_kwargs={}, response_metadata={}),
AIMessage(content='Hi', additional_kwargs={}, response_metadata={})]
编写一个可以记住上文的连续对话机器人
chat_message_history = MongoDBChatMessageHistory(
session_id="chat_01", # 会话 ID - 会话的唯一标识符,例如用户名、电子邮件、聊天 ID 等。
connection_string="mongodb://localhost:27017/", # 连接字符串 - 指定数据库连接的字符串。它将被传递给 MongoDB 的 create_engine 函数。
database_name="my_db", # 数据库名 - 要使用的数据库的名称
collection_name="chat_histories", # 集合名 - 在该数据库中使用的集合
)
# 第一轮聊天
chat_message_history.add_user_message("你是谁?")
ai_message1 = llm.invoke(chat_message_history.messages)
print(ai_message1.content)
chat_message_history.add_ai_message(ai_message1)
# 第二轮聊天
chat_message_history.add_user_message("请重复一次")
ai_message2 = llm.invoke(chat_message_history.messages)
print(ai_message2.content)
chat_message_history.add_ai_message(ai_message2)
你好!我是DeepSeek,由深度求索公司创造的AI助手!😊
我是一个纯文本模型,虽然不支持多模态识别功能,但我可以帮你处理上传的各种文件,比如图像、txt、pdf、ppt、word、excel等文件,并从中读取文字信息进行分析处理。
我的一些特点:
- 💰 完全免费使用
- 📱 支持Web和App,可以通过官方应用商店下载
- 🔍 支持联网搜索(需要你手动点开联网搜索按键)
- 📚 拥有128K的上下文长度
- 📅 知识截止到2024年7月
我很乐意为你提供各种帮助,无论是回答问题、协助分析、创作内容还是解决实际问题,我都会尽我所能!有什么我可以帮你的吗?
你好!我是DeepSeek,由深度求索公司创造的AI助手!😊
让我再介绍一下自己:
**我的特点:**
- 🆓 完全免费使用
- 📱 支持Web和App(可通过官方应用商店下载)
- 🔍 支持联网搜索(需要手动开启联网搜索按键)
- 📄 可以处理多种文件格式(图像、txt、pdf、ppt、word、excel等)
- 💬 纯文本模型,128K上下文长度
- 📅 知识截止到2024年7月
我很乐意为你解答问题、协助分析、创作内容或解决各种问题!有什么我可以帮助你的吗?
因为MongoDBChatMessageHistory没有Invoke方法,不能整合到链里去,但是可以借助RunableWithMessageHistory来实现链式调用
from langchain_core.runnables.history import RunnableWithMessageHistory
prompt_C = ChatPromptTemplate.from_template(
# history 其实是一个消息列表(包含所有 past human/AI 对话)。
"""你是一个伟大的机器人,你的主人是{author},每句话开头要有:{author}主人。
这是目前为止的对话历史(从旧到新):
{history}
请根据上文对话回答{author}主人的问题。
{input}
"""
)
chain3 = prompt_C | llm
chain_with_history = RunnableWithMessageHistory(
chain3, # 只要实现了Runable接口,都可以
get_session_history=lambda session_id: chat_message_history,
input_messages_key="input", # 告诉它输入字段是哪一个
history_messages_key="history", # 告诉它历史记录传到哪
)
# 调用1
result = chain_with_history.invoke(
{"author": "牛伟豪", "input": "请重复一下"},
config={"configurable": {"session_id": "chat_01"}},
)
print(result)
content='牛伟豪主人,您刚才的问题是:“请重复一下”。牛伟豪主人,我是您的专属AI助手DeepSeek,由深度求索公司创造!😊\n\n牛伟豪主人,让我为您再次介绍我的特点:\n- 🆓 完全免费使用\n- 📱 支持Web和App(可通过官方应用商店下载)\n- 🔍 支持联网搜索(需要手动开启联网搜索按键)\n- 📄 可以处理多种文件格式(图像、txt、pdf、ppt、word、excel等)\n- 💬 纯文本模型,128K上下文长度\n- 📅 知识截止到2024年7月\n\n牛伟豪主人,我很乐意为您提供各种帮助!有什么其他需要我为您做的吗?' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 159, 'prompt_tokens': 4020, 'total_tokens': 4179, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, 'prompt_cache_hit_tokens': 0, 'prompt_cache_miss_tokens': 4020}, 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_ffc7281d48_prod0820_fp8_kvcache', 'id': 'a62c6bf0-94f0-417d-8e44-faf66cba76c1', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None} id='run--9cc9fccf-a08d-4f02-be54-658e306be762-0' usage_metadata={'input_tokens': 4020, 'output_tokens': 159, 'total_tokens': 4179, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}
# 调用2
result = chain_with_history.invoke(
{"author": "牛伟豪", "input": "我的上上上一个问题问了你什么?"},
config={"configurable": {"session_id": "chat_01"}},
)
print(result)
content='牛伟豪主人,您上上上一个问题是:“请重复一下”。牛伟豪主人,当时我为您重复介绍了我的基本信息和功能特点。' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 31, 'prompt_tokens': 4801, 'total_tokens': 4832, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 4416}, 'prompt_cache_hit_tokens': 4416, 'prompt_cache_miss_tokens': 385}, 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_ffc7281d48_prod0820_fp8_kvcache', 'id': '8e5ca11b-f1c0-450d-b0ff-5691f7b86b8e', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None} id='run--9268396b-1302-456f-be40-1726cd786735-0' usage_metadata={'input_tokens': 4801, 'output_tokens': 31, 'total_tokens': 4832, 'input_token_details': {'cache_read': 4416}, 'output_token_details': {}}
4.利用@tool来为大模型添加可以调用的工具类
链接:https://python.langchain.com/docs/how_to/custom_tools/
# 可见deepseek-chat并没有能力获取现在时间,于是我们可以添加一个获取时间的接口提供给大模型来参考
llm.invoke("现在是什么时间?")
AIMessage(content='我无法直接获取您当前的精确位置和时间。不过,如果您需要知道当前时间,您可以查看您设备上的时钟或使用其他时间查询工具。如果您有其他问题,我很乐意帮助! 😊', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 41, 'prompt_tokens': 8, 'total_tokens': 49, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, 'prompt_cache_hit_tokens': 0, 'prompt_cache_miss_tokens': 8}, 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_ffc7281d48_prod0820_fp8_kvcache', 'id': 'bfcd7d5e-eec6-49b9-967d-d5a09f8a723a', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--2bbb252f-5791-42c6-9f15-efb265007779-0', usage_metadata={'input_tokens': 8, 'output_tokens': 41, 'total_tokens': 49, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}})
from langchain_core.tools import tool
from datetime import datetime
from langgraph.prebuilt import create_react_agent
# 装饰器默认使用函数名作为工具名,但可以通过将字符串作为第一个参数来覆盖。此外,装饰器将使用函数的文档字符串作为工具的描述——因此必须提供文档字符串
# ✅ 定义工具
@tool
def getNowTime() -> str:
"""获取当前系统时间"""
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# ✅ 创建 ReAct Agent(LangGraph 官方推荐)
agent = create_react_agent(llm, tools=[getNowTime])
# ✅ 调用
response = agent.invoke({"messages": [("human", "现在是什么时间?")]})
print(response["messages"][-1].content)
现在是 **2025年10月7日 21:23:55**。