langchain实战-从0到1搭建ai聊天机器人

介绍

当前,人工智能大模型公司如雨后春笋般迅速涌现,例如 OpenAI、文心一言、通义千问等,它们提供了成熟的 API 调用服务。然而,随之而来的是不同公司的繁琐协议接入过程,这让许多开发者感到头疼不已。有没有一种统一的工具,能够让我们一次性接入所有公司的 API 协议,并且基于它们的底层能力封装出各种酷炫功能呢?今天,这样的工具终于来了——Langchain,它以坚实的步伐走来,为我们带来了极大的便利和创新。

Langchain 是一个专为适配各家大模型 API 而生的框架,不仅如此,它还封装了各种重要模块,使得大家能够轻松搭建出各种令人惊叹的人工智能应用。以下代码基于 langchain 2.0 版本实现

模块介绍:

  • Model: 这一模块的重要性不言而喻。Langchain 的 Model 模块致力于适配各大模型公司的接口协议,使得接入过程更加简单和高效。不再需要为每个公司的特殊协议而烦恼,Langchain 帮助您一次性搞定。

  • Prompt: 提示词的运用是大模型输出准确性的关键。Langchain 的 Prompt 模块不仅让大模型能更准确地输出我们期望的回答,还衍生出了“提示工程”。建议在使用大模型之前先查看提示工程,以获得更好的结果和体验。

  • History: 大模型本身并不具备记忆功能,这带来了一个看似矛盾的问题:为什么像 ChatGPT 这样的模型能够联系到我们之前的提问并给出相关回复呢?Langchain 的 History 模块揭示了这个谜团的解答。其实,实现原理非常简单,只需将你的上一个提问一并发送给大模型即可。当然,实际实现中还涉及一些问题,比如如何标识同一轮对话、信息存储位置、处理过多文本等等。因此,需要自行实现部分逻辑,但 Langchain 为您提供了思路和基础。

言归正传,让我们开始实战代码,探索 Langchain 带来的无限可能吧!

快速开始

1. 先安装依赖,以openai为例

pip install langchainpip install -qU langchain-openai

2. 初始化model

import osos.environ["OPENAI_API_KEY"] = "sk-xxx"from langchain_openai import ChatOpenAImodel = ChatOpenAI(model="gpt-3.5-turbo")

3. 发起请求

from langchain_core.messages import HumanMessageresponse = model.invoke([HumanMessage(content="你好")])response.content

4.得到回答

'你好!有什么可以帮助你的吗?'

🎉 恭喜你,你已经可以成功使用langchain调用大模型api了

加入历史记忆实现连续对话

经过以上步骤,你已经可以跟大模型进行聊天,但是有个问题,现在他是不会记忆上一轮的回答的,你上一句问他东西,他转头就忘了,那该怎么办呢?那就给他加上历史记忆好了

# 没有 history memoryfrom langchain_core.messages import HumanMessagequestion_1 = "你好,我叫小明"
result_1 = model.invoke([HumanMessage(content=f"{question_1}")])
print(result_1.content)question_2 = "我叫什么名字"
result_2 = model.invoke([HumanMessage(content=f"{question_2}")])
print(result_2.content)

返回结果

你好,小明!有什么可以帮助你的吗?
抱歉,我无法回答这个问题,因为我不知道您的名字。您可以告诉我您的名字吗?我会很高兴称呼您的名字。

开头也说了,大模型是没有记忆功能的,目前业界的实现方式都是通过各自实现存储,在聊天中将上一轮的问答也一起发送过去,让大模型有了“记忆”,那最简单的方法就是用个list存储,然后每次回答都带上去就好了

# 简单实现 history memoryfrom langchain_core.messages import HumanMessagestore = []question_1 = "你好,我叫小明"
result_1 = model.invoke([HumanMessage(content=f"{question_1}")])
print(result_1.content)store.append({"human": question_1, "ai": result_1.content})question_2 = "我叫什么名字"
result_2 = model.invoke([HumanMessage(content=f"history: {store} {question_2} ")])
print(result_2.content)

返回结果:

你好,小明!有什么可以帮助你的吗?
你的名字是小明。有什么可以帮助你的吗?如果有任何问题,随时问我吧!

神奇的事情发生了,大模型有“记忆”了 

当然,langchain也为我们提供了方便的实现,让我们不用显式的写history

pip install langchain_community
# 使用官方模块实现from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistorystore = {}def get_session_history(session_id: str) -> BaseChatMessageHistory:if session_id not in store:store[session_id] = ChatMessageHistory()return store[session_id]with_message_history = RunnableWithMessageHistory(model, get_session_history)config = {"configurable": {"session_id": "abc2"}}question_1 = "你好,我叫小明"
result_1 = with_message_history.invoke([HumanMessage(content=f"{question_1}")],config=config)
print(result_1.content)question_2 = "我叫什么名字"
result_2 = with_message_history.invoke([HumanMessage(content=f"{question_2}")],config=config)
print(result_2.content)
你好小明,有什么可以帮助你的吗?
你告诉我你叫小明。

同时langchain还提供了更多类型的memory实现,让我们可以使用redis去存储历史记录,这个就留给大家自己实现了  Redis | 🦜️🔗 LangChain

加入提示词prompt格式化回答

在上述的实现中,我们的做法就是简单的字符串拼接发送给大模型,使用prompt可以让我们更好的格式化我们的输入

# 加入promptfrom langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholderstore = {}def get_session_history(session_id: str) -> BaseChatMessageHistory:if session_id not in store:store[session_id] = ChatMessageHistory()return store[session_id]prompt = ChatPromptTemplate.from_messages([("system","在每一句话结尾都加上 回复完毕",),MessagesPlaceholder(variable_name="messages"),]
)chain = prompt | modelwith_message_history = RunnableWithMessageHistory(chain, get_session_history)config = {"configurable": {"session_id": "abc2"}}question_1 = "你好,我叫小明"
result_1 = with_message_history.invoke([HumanMessage(content=f"{question_1}")],config=config)
print(result_1.content)question_2 = "我叫什么名字"
result_2 = with_message_history.invoke([HumanMessage(content=f"{question_2}")],config=config)
print(result_2.content)
你好,小明。有什么可以帮助你的吗?回复完毕
您的名字是小明。回复完毕

🎉 这样你就完成了一个能连续对话的ai机器人啦

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/15184.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot + Redis实现对接口的限流

目录 前言 什么是限流? 实现限流 创建一个注解类 接着创建一个切面类 前言 在项目中,对于接口的限流,是任何项目都必不可少的一部分,主要是为了防止用户频繁的发送请求,对服务器造成压力。 另外一点就是防止外来攻…

C++之第八课

课程列表 今天我们来学一学C里的一些实用的东西。 1.域宽 说到域宽setw&#xff0c;就叒要加头文件了。 #include<iomanip> 使用格式是&#xff1a; cout<<setw(5)<<"123"; setw括号里面可以改数字&#xff0c;后面就是输出内容了&#xff…

COD论文笔记 Boundary-Guided Camouflaged Object Detection

动机 挑战性任务&#xff1a;伪装物体检测&#xff08;COD&#xff09;是一个重要且具有挑战性的任务&#xff0c;因为伪装物体往往与背景高度相似&#xff0c;使得准确识别和分割非常困难。现有方法的不足&#xff1a;现有的深度学习方法难以有效识别伪装物体的结构和细节&am…

MySQL索引、视图练习

素材 1.学生表&#xff1a;Student (Sno, Sname, Ssex , Sage, Sdept) 学号&#xff0c;姓名&#xff0c;性别&#xff0c;年龄&#xff0c;所在系 Sno为主键 2.课程表&#xff1a;Course (Cno, Cname,) 课程号&#xff0c;课程名 Cno为主键 3.学生选课表&#xff1a;SC (Sno…

Home Credit - Credit Risk Model Stability

本篇是对Kaggle上Home Credit - Credit Risk Model Stability竞赛中的开源代码VotingClassifier Home Credit的解读。原链接在VotingClassifier Home Credit (kaggle.com)。 %%writefile script.py import sys from pathlib import Path import subprocess import os import g…

浅谈JMeter运行原理

浅谈JMeter运行原理 JMeter架构基础 JMeter基于Java平台开发&#xff0c;运行于Java虚拟机&#xff08;JVM&#xff09;之上。这意味着它可以在任何支持JVM的操作系统上运行&#xff0c;包括Windows、Linux、macOS等。其核心架构设计围绕着多线程执行机制&#xff0c;这使得它…

AI大模型探索之路-实战篇6: Function Calling技术调研之详细流程剖析

系列篇章&#x1f4a5; AI大模型探索之路-实战篇4&#xff1a;DB-GPT数据应用开发框架调研实践 AI大模型探索之路-实战篇5&#xff1a; Open Interpreter开放代码解释器调研实践 目录 系列篇章&#x1f4a5;一、前言二、Function Calling详细流程剖析1、创建OpenAI客户端2、定…

PCL 法向量加权的RANSAC拟合分割平面

目录 一、算法原理1、原理概述2、主要函数二、代码实现三、结果展示四、相关链接本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、算法原理 1、原理概述

鸿蒙布局List简介

鸿蒙布局List简介 List--常见的布局容器List 创建方式创建方式一&#xff0c;通过Listitem创建方式二&#xff0c;通过ForEach和Listitem创建方式三&#xff0c;通过ListItemGroup List–常见的布局容器 List是在app开发中最常见的一种布局方式&#xff0c;例如通讯录、新闻列…

Wpf 使用 Prism 实战开发Day24

自定义询问窗口 当需要关闭系统或进行删除数据或进行其他操作的时候&#xff0c;需要询问用户是否要执行对应的操作。那么就需要一个弹窗来给用户进行提示。 一.添加自定义询问窗口视图 (MsgView.xaml) 1.首先&#xff0c;添加一个自定义询问窗口视图 (MsgView.xaml) <Use…

域内攻击 ----->约束非约束委派攻击

在域中&#xff0c;除了我们常见的横向移动以外&#xff0c;还有很多攻击&#xff0c;像什么kerberoasting&#xff0c;委派攻击&#xff0c;NTLMrelay啊...... 还有很多&#xff08;暂时只知道这些&#xff09; 以前在一篇公众号看到的一个笑话也荟萃了网安的一些攻击手法&am…

《拯救大学生课设不挂科第二期之Windows11下安装VC6.0(VC++6.0)与跑通Hello World C语言程序教程》【官方笔记】

背景与目标人群&#xff1a; 大学第一次学C语言的时候&#xff0c;大部分老师会选择VC6这个编辑器。 但由于很多人是新手&#xff0c;第一次上大学学C语言。 老师要求VC6.0&#xff08;VC6.0&#xff09;写C语言跑程序可能很多人还是第一次接触电脑。 需要安装VC6这个编辑器…

初识Java--开启我的Java学习之旅

目录 一、JAVA语言概述二、JAVA语言的重要性2.1语言使用广泛程度2.2工作领域2.3在校招岗位的需求2.4 java语言发展简史2.5Java语言特性 三、初识java的main方法四、运行java程序五、【面试题】JDK、JRE、JVM之间的关系&#xff1f; 一、JAVA语言概述 Java是一种优秀的程序设计…

【Apache Doris】周FAQ集锦:第 4 期

【Apache Doris】周FAQ集锦&#xff1a;第 4 期 SQL问题数据操作问题运维常见问题其它问题关于社区 欢迎查阅本周的 Apache Doris 社区 FAQ 栏目&#xff01; 在这个栏目中&#xff0c;每周将筛选社区反馈的热门问题和话题&#xff0c;重点回答并进行深入探讨。旨在为广大用户和…

Redis常见数据类型(6)-set, zset

目录 Set 命令小结 内部编码 使用场景 用户画像 其它 Zset有序集合 普通指令 zadd zcard zcount zrange zrevrange ​编辑 zrangebyscore zpopmax/zpopmin bzpopmax/bzpopmin zrank/zrevrank zscore zrem zremrangebyrank zremrangebyscore Set 命令小结 …

Spring 模拟管理Web应用程序

MVC&#xff1a;Model View Controller 1&#xff09;controller&#xff1a;控制层&#xff08;Servlet是运行服务器端&#xff0c;处理请求响应java语言编写技术&#xff09; 2&#xff09;service&#xff1a;业务层&#xff08;事务&#xff0c;异常&#xff09; 3&#xf…

视频号小店的保证金是多少钱?2024最新收费标准,一篇了解!

哈喽~我是电商月月 现实社会&#xff0c;干什么都需要交钱&#xff0c;就连上班&#xff0c;路费也得掏钱 想要入驻视频号小店&#xff0c;在视频号里卖货赚钱&#xff0c;就要缴纳类目保证金 那到底要缴多少钱呢&#xff1f; 今天&#xff0c;月月就把最新的收费标准分享给…

轻松拿捏C语言——【字符串函数】的使用及模拟实现

&#x1f970;欢迎关注 轻松拿捏C语言系列&#xff0c;来和 小哇 一起进步&#xff01;✊ &#x1f389;创作不易&#xff0c;请多多支持&#x1f389; &#x1f308;感谢大家的阅读、点赞、收藏和关注&#x1f495; &#x1f339;如有问题&#xff0c;欢迎指正 感谢 目录 一、…