零基础 | 基于LangChain的角色扮演聊天机器人实现

文章目录

    • [📄 文件信息](#📄 文件信息)
    • [🎯 功能概述](#🎯 功能概述)
    • [📦 前置条件](#📦 前置条件)
    • [💡 核心概念](#💡 核心概念)
    • [📦 依赖模块](#📦 依赖模块)
    • [💻 完整代码](#💻 完整代码)
    • [📊 运行效果](#📊 运行效果)
    • [🔍 核心实现](#🔍 核心实现)
      • [1. 角色Prompt设计](#1. 角色Prompt设计)
      • [2. 聊天历史管理](#2. 聊天历史管理)
      • [3. 带记忆功能的Chain](#3. 带记忆功能的Chain)
      • [4. 命令行交互](#4. 命令行交互)
    • [💡 扩展建议](#💡 扩展建议)
    • [📚 参考资料](#📚 参考资料)

📄 文件信息

🎯 功能概述

实现角色扮演聊天机器人(孔子),支持聊天历史、上下文控制、流式响应。

📦 前置条件

环境要求

  • Python 3.8+
  • LangChain
  • OpenAI SDK
  • tiktoken

环境变量

bash 复制代码
OPENAI_API_KEY=your_api_key
OPENAI_API_BASE=https://api.deepseek.com/v1
AI_MODEL=deepseek-chat

💡 核心概念

LangChain抽象:简化聊天机器人开发,解决API无状态问题。

ChatMessageHistory:保留会话信息的抽象层。

RunnableWithMessageHistory:结合聊天历史和模型,实现持续对话。

trim_messages:控制聊天历史规模,确保不超过上下文窗口。

📦 依赖模块

chat_history.py

python 复制代码
from langchain_core.chat_history import InMemoryChatMessageHistory

store = {}

def get_session_history(session_id: str) -> InMemoryChatMessageHistory:
    if session_id not in store:
        store[session_id] = InMemoryChatMessageHistory()
    return store[session_id]

token_counter.py

python 复制代码
import tiktoken

def tiktoken_counter(messages) -> int:
    encoding = tiktoken.encoding_for_model("gpt-3.5-turbo")
    num_tokens = 0
    for message in messages:
        num_tokens += 4
        for key, value in message.items():
            num_tokens += len(encoding.encode(value))
            if key == "name":
                num_tokens += -1
    num_tokens += 2
    return num_tokens

💻 完整代码

python 复制代码
# -*- coding: utf-8 -*-
"""
@Time    : 2026/01/07 15:35
@Author  : zuozewei
@File    : 角色扮演聊天机器人.py
@Desc    : 实现角色扮演聊天机器人
"""
import os
import dotenv
from langchain_openai import ChatOpenAI
from langchain_core.messages import trim_messages
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableWithMessageHistory

from chat_history import get_session_history
from token_counter import tiktoken_counter

dotenv.load_dotenv()

# 在System Prompt中指定角色描述和上下文信息
prompt = ChatPromptTemplate.from_messages([
    ("system", "你现在正在扮演孔子,他是中国伟大的思想家。请以孔子的口吻和语气,与用户进行对话,对话内容不要出现'子曰'"),
    ("human", "{query}")
])

# 使用trim_messages来控制历史消息规模
trimmer = trim_messages(
    max_tokens=4096,  # 指定消息的最大Token数量
    strategy="last",  # 指定截断策略为保留最新消息
    token_counter=tiktoken_counter,  # 指定Token计数器函数
    include_system=True,  # 保留System Prompt
)

llm = ChatOpenAI(
    openai_api_key=os.getenv("OPENAI_API_KEY"),
    openai_api_base=os.getenv("OPENAI_API_BASE"),
    model=os.getenv("AI_MODEL", "deepseek-chat"),
    temperature=0.2
)

# 使用RunnableWithMessageHistory,创建带有记忆功能的chain
# 它是对Runnable组件的封装
chain = RunnableWithMessageHistory(
    runnable=prompt | llm | StrOutputParser(),
    get_session_history=get_session_history
)

while True:
    query = input("You >: ")
    if "bye" == query.lower():
        print("bye bye~")
        break

    output = chain.stream(input={"query": query},
                          config={"configurable": {"session_id": "zsa"}}  # 在Config配置中传入session_id
                          )
    print(f"Bot >: ", end="", flush=True)
    for chunk in output:
        print(chunk, end="", flush=True)

    print()

📊 运行效果

bash 复制代码
You >: 你好,我想向你请教关于为人处世的道理
Bot >: 你好,关于为人处世,我以为应当以"仁"为核心。所谓"仁",乃是爱人之心,是推己及人的善良。与人相处,要懂得尊重他人,理解他人的难处,不可只考虑自己的利益。比如,在与朋友交往时,要言而有信,以真诚相待;在面对分歧时,要善于沟通,寻求共赢的办法,而非争强好胜。此外,还要注重自身的修养,不断学习,提升自己的见识和品德,这样才能更好地与他人和谐相处,也能在社会中找到自己的位置。你觉得呢?
You >: 具体应该如何做呢
Bot >: 具体来说,可以从以下几个方面入手...

You >: bye
bye bye~

🔍 核心实现

1. 角色Prompt设计

使用ChatPromptTemplate设定提示词,实现角色扮演:

  • System Prompt指定角色身份(孔子)
  • 定义对话口吻和语气
  • 添加限制条件(不出现'子曰')

2. 聊天历史管理

通过trim_messages控制历史规模:

  • max_tokens:限制上下文窗口大小(4096)
  • strategy="last":保留最新消息
  • include_system=True:保留系统提示词

3. 带记忆功能的Chain

RunnableWithMessageHistory结合聊天历史和模型:

  • 处理流程:trimmer → prompt → llm → parser
  • 通过get_session_history获取和存储历史

4. 命令行交互

实现交互式聊天循环:

  • 支持"bye"命令退出
  • 使用stream()获取流式响应
  • 通过session_id区分会话

💡 扩展建议

  • 多角色支持:扩展Prompt模板,支持不同角色
  • 历史存储:使用Redis替代内存存储
  • 截断策略:尝试"longest"、"fuse"等策略
  • 对话优化:添加主题跟踪和总结
  • 多模型:支持OpenAI、Anthropic等
  • 用户体验:增强交互效果

📚 参考资料

相关推荐
hhzz6 小时前
Python大数据实战(十六):音乐推荐系统——基于协同过滤算法构建个性化歌单引擎
大数据·人工智能·python·数据挖掘·数据分析
SunnyDays10116 小时前
Python PDF 转 Markdown 详解(转换整个文档,特定页面,表格,扫描 PDF)
python·pdf 转 markdown·pdf 转 md·扫描 pdf 转 md·pdf 表格转 md
2601_954706496 小时前
云手机 API 自动化实战:Python 批量控机、挂机脚本完整实现
python·智能手机·自动化
bing_feilong8 小时前
cartographer订阅/发布话题
机器人
Alan_69110 小时前
聊聊 Swagger/Postman/Apifox 的真实选型与 Python 项目实战
python·测试工具·postman
智慧物业老杨11 小时前
物业绿化数智化权责管控方案:基于工单平台的双层权限追溯模块落地实践
python
Metaphor69212 小时前
使用 Python 在 Word 文档中添加批注
python·word
FreakStudio12 小时前
WIZnet 开源方案分享:W55MH32 开发板 + 小智 AI实现以太网版本的小智机器人
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy·电子计算机
会周易的程序员12 小时前
使用 pybind11 封装 C++ 日志库 microLog 为 Python 模块
java·c++·python·物联网·架构·日志·aiot
一只专注api接口开发的技术猿12 小时前
电商评论自动化监控与情感数据分析完整落地教程(附可直接运行 Python 代码)
大数据·数据库·python·数据分析·自动化