基于Langchain + DeepSeek 构建聊天机器人
发布于 10 小时前 作者 pangguoming 8 次浏览 来自 LangChain

基于Langchain + DeepSeek 构建聊天机器人

前言

本文主要介绍如何基于 DeepSeek 来创建一个聊天机器人。首先介绍 PromptTemplate 提示模版,它作为设计对话流的基础,能够极大提升用户体验。接着,深入 DeepSeek 环境准备及模型创建过程,包括获取 API、创建和配置 API Key、设置 base_url 以及选择合适的模型等步骤。基于 Langchain 框架,将介绍如何通过 MessagesPlaceholder 处理复杂的多轮对话,构建 Chain 保存对话历史,并了解 RunnableWithMessageHistory 对象的实现流式输出,并通过示例代码演示整个流程的实际运行效果。

备注:本系列文章基于 B 站课程:马士兵-AI 大模型全套教程(学习路线+LLM 大语言模型+RAG 实战+Langchain+ChatGLM-4+Transformer+DeepSeek)学习整理得到。


1. 使用 PromptTemplate 提示模板

Langchain 提供了一个提示词模板 ChatPromptTemplate,它用来帮助我们构建提示词。可以简单理解为 Python 的字符串拼接模板。

定义提示模版

from langchain_core.prompts import ChatPromptTemplate

prompt_template = ChatPromptTemplate.from_messages(
    [("system", '请将以下的内容翻译成{language}'), ("user", "{text}")]
)

完整使用代码及运行结果

import os
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

os.environ["OPENAI_API_KEY"] = "DEEPSEEK_API_KEY"

# 1. 创建模型
model = ChatOpenAI(
    model='deepseek-chat',
    base_url="https://api.deepseek.com/v1"
)

# 2. 定义提示模版
prompt_template = ChatPromptTemplate.from_messages(
    [("system", '请将以下的内容翻译成{language}'), ("user", "{text}")]
)

# 3. 创建返回的数据解析器
parser = StrOutputParser()

# 4. 创建链 chain
chain = prompt_template | model | parser

# 5. 直接使用 chain 进行调用
result = chain.invoke({"language": "English", "text": '我下午还有一节课,不能去打球了'})
print(result)

image

2. DeepSeek 环境准备及模型创建

2.1 获取 API

访问 DeepSeek 开放平台。 image

2.2 创建 API Key

在左侧点击 API Keys,然后创建 API Key。 image

2.3 配置 API KEY

os.environ["OPENAI_API_KEY"] = "your_key"

将上一步中创建的 Key 配置到环境变量中。

2.4 配置 base_url

model = ChatOpenAI(
    base_url="https://api.deepseek.com"
)

代理地址或中转地址填写 "https://api.deepseek.com"
注意:出于与 OpenAI 兼容考虑,也可以将 base_url 设置为 "https://api.deepseek.com/v1"

2.5 配置 model

model = ChatOpenAI(
    model='deepseek-reasoner',
    base_url="https://api.deepseek.com/v1"
)
  • deepseek-reasoner 是 DeepSeek 最新推出的推理模型 DeepSeek-R1。
  • 通过指定 model='deepseek-reasoner',即可调用 DeepSeek-R1。
  • 注意:通过指定 model='deepseek-chat',即可调用 DeepSeek-V3。

3. Langchain 构建聊天机器人

这个聊天机器人能够进行对话并记住之前的互动。

3.1 引入 MessagesPlaceholder 来处理多轮对话

MessagesPlaceholder 用于在 Prompt 中插入历史消息,支持多轮对话。动态的系统消息可以通过 {} 进行参数化。

# 定义提示模版
prompt_template = ChatPromptTemplate.from_messages([
    ('system', '你是一个乐于助人的助手。用{language}尽你所能回答所有问题。'),
    MessagesPlaceholder(variable_name='my_msg')
])

3.2 构建 Chain 和保存对话历史

LangChain 提供了 RunnableWithMessageHistoryChatMessageHistory 来支持多轮对话,并保存对话的历史记录。

store = {}  # 所有用户的聊天记录都保存到 store。key: session_id, value: 历史聊天记录

# 此函数预期将接受一个 session_id,并返回与该 session_id 对应的聊天记录
def get_session_history(session_id: str):
    if session_id not in store:
        store[session_id] = ChatMessageHistory()
    return store[session_id]

do_message = RunnableWithMessageHistory(
    chain,
    get_session_history,
    input_messages_key='my_msg'  # 每次聊天时发送 msg 的 key
)

3.3 调用 RunnableWithMessageHistory 对象的 invoke() 方法

每次调用 do_message.invoke() 时,都会根据当前会话的 sessionId 获取或创建对应的对话历史。

config = {'configurable': {'session_id': 'ls1234'}}  # 给当前会话定义一个 sessionId

# 第一轮对话
resp1 = do_message.invoke(
    {
        'my_msg': [HumanMessage(content='你好啊! 我是孙悟空')],
        'language': '中文'
    },
    config=config
)
print(resp1.content)

# 第二轮对话
resp2 = do_message.invoke(
    {
        'my_msg': [HumanMessage(content='请问:我有其它的昵称吗')],
        'language': '中文'
    },
    config=config
)
print(resp2.content)

3.4 流式输出

LangChain 支持流式响应,这对于处理长文本或实时交互非常有用。

# 第三轮对话 返回的数据是流式的
config = {'configurable': {'session_id': 'lishi987'}}  # 给当前会话定义一个 sessionId
for resp in do_message.stream(
        {'my_msg': [HumanMessage(content='81难后,我该成仙还是成佛? 或者入魔?')],
         'language': '中文'},
        config=config):
    # 每一次 resp 都是一个 token
    print(resp.content, end='-')

3.5 示例代码及运行效果

from langchain_core.messages import HumanMessage
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
import os
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.runnables import RunnableWithMessageHistory
from langchain_openai import ChatOpenAI

os.environ["OPENAI_API_KEY"] = "YOUR_API_KEY"

# 1. 创建模型
model = ChatOpenAI(
    model='deepseek-chat',
    base_url="https://api.deepseek.com/v1"
)

# 2. 定义提示模版,引入 MessagesPlaceholder 来处理多轮对话
prompt_template = ChatPromptTemplate.from_messages([
    ('system', '你是一个乐于助人的助手。用{language}尽你所能回答所有问题。'),
    MessagesPlaceholder(variable_name='my_msg')
])

# 3. 创建链 chain
chain = prompt_template | model

# 4. 定义函数保存和管理对话历史
store = {}

def get_session_history(session_id: str):
    if session_id not in store:
        store[session_id] = ChatMessageHistory()
    return store[session_id]

# 5. 将 Chain 和对话历史管理器对象结合
do_message = RunnableWithMessageHistory(
    chain,
    get_session_history,
    input_messages_key='my_msg'
)

config = {'configurable': {'session_id': 'ls1234'}}

# 6. 调用对话历史管理器对象的 invoke() 及 stream() 方法,进行对话
# 第一轮对话
resp1 = do_message.invoke(
    {
        'my_msg': [HumanMessage(content='你好啊! 我是孙悟空')],
        'language': '中文'
    },
    config=config
)
print(resp1.content)

# 第二轮对话
resp2 = do_message.invoke(
    {
        'my_msg': [HumanMessage(content='请问:我有其它的昵称吗')],
        'language': '中文'
    },
    config=config
)
print(resp2.content)

# 第三轮对话 返回的数据是流式的
config = {'configurable': {'session_id': 'lishi987'}}
for resp in do_message.stream(
        {'my_msg': [HumanMessage(content='81难后,我该成仙还是成佛? 或者入魔?')],
         'language': '中文'},
        config=config):
    print(resp.content, end='-')

image

回到顶部