LangChain原理学习笔记

2f24e90848a87ab641b13102e4189097.gif

最新越发觉得AI的发展,对未来是一场革命,LangChain已经在工程设计上有了最佳实践,类似于AI时代的编程模型或编程框架,有点Spring框架的意思。之前在LangChain上也有些最佳实践,所以在这里分享记录下。

d98d36446d1f6a38ab44adc2131cd45c.png

LangChain解决什么问题

LangChain是基于LLM之上的,在应用层和底层LLM之前的一个很好的编程框架,如果把LLM比喻为各种类型的数据库、中间件等这些基础设施,应用层是各种业务逻辑的组合之外,那么LangChain就负责桥接与业务层和底层LLM模型,让开发者可以快速地实现对接各种底层模型和快速实现业务逻辑的软件开发框架。

那么LangChain是如何做到的呢?试想一下,现在底层有一个大模型的推理能力,除了在对话框手动输入跟他聊天之外。如何用计算机方式跟它互动呢?如果把一次LLM调用当作一个原子能力,如何编排这些原子能力来解决一些业务需求呢?Langchain就是来解决这个事情的。

3844ed5ddadeb8b9e9cc427c5fb8a2f7.png

LangChain的几个核心概念

  Model I/O

这里重点把背后的LLM模型做了一层封装,开发者可以通过更改配置的方式快速切换底层LLM模型,比如chatgpt,chatGLM、通义千问等模型。

同时还有些高阶功能:比如提供了缓存等功能,这样对于语义上类似的query,如果缓存有,那么langchain可以快速返回结果,而不需要调用大模型。

  Retriver

检索是为了解决大模型打通用户的本身数据,做一些面向业务属性的东西。这里的检索并非传统的关系型数据库,更多的是与大模型的本身逻辑相似的,比如向量数据库。

一个经典的结合LLM和外部用户的文档进行智能答疑的场景

文档->分词->embedding->向量数据库

query->向量数据库查询->TOP N->上下文+ 用户提问 + prompt -> LLM -> 返回结果

一个经典的图如下:

e92aaaa2dba2398706eb901bf92ab077.png

关键技术:文档如何拆分、embedding过程、 TOPN 向量距离的选择

embedding技术选型

embedding是将现实中的物体通过向量化的方法转化为高维向量,可被机器学习模型所识别。他是一种映射,同时也保证了能清晰地表达现实物体的特征。基于此,可以进行一些归类分析、回归分析等。

现在市面上常见的embedding方法有通义千问的embedding等方法。

向量数据库:

向量数据库底层存储的是一堆向量,它提供了根据向量相似度进行查询的能力,一般情况下,向量相似度代表了现实世界中物体的相似度。比如”我的名字是小明“ 和“我叫小明”这两句话所代表的含义几乎是相同的,那么在embedding之后,基于向量数据库进行查询的时候,它们俩的相似度就会很近。

  Chain

各种类型的chain,chain代表了各种业务类型的组合,类似于工作流的编排。

  Memory

LLM本身提供了记忆的能力,同时提供了接口,开发者可以将历史的对话记录传入给LLM。LangChain需要使用外部存储保存这些历史的会话和记忆。可以使用数据库、缓存等进行保存。

  Agent

重点是代理工具

代理工具可以让应用程序基于大模型的推理能力,然后进行代理工具或代理服务的调用。因为LLM是没有“联网”的能力的,如果想解决特定的应用场景,代理工具是个完美的选择。

代理工具通常包含三个方面:用户输入、prompt编排LLM思考与路由代理的过程、背后的代理服务。其中难点可能就在于prompt设计了。通常的“套路”是这样的:

ReAct 模型

输入:用户的问题

思考过程:如果是情况1(这个是需要LLM进行意图识别进行思考的),那么推理和提取出一些关键参数,调用agent1,如果是情况2,那么推理和提取出一些关键参数,调用agent2

Act:调用agent1对应一个JSON格式化的输入,调用function1,返回结果。

观察:观察调用后的结果,再结合推理的能力,再进行循环思考。

4460487d4dcfd750a9bb0e9e295427ee.png

LangChain的在实际场景中的实践

集团内部开发了一个JAVA版本的LangChain框架,以下实践基于此框架与开源大模型chatGLM-6B进行。

  淘宝开放平台智能问答

淘宝开放平台对内托管了上万个API,每天在内部群里都会有开发者咨询API发布问题,之前我们是通过NLP来实现智能问答的,现将它升级为基于大模型的智能问答,以下是具体的技术实现过程。

  • 知识库Embedding过程

由于之前已经沉淀好了很多知识库,都是Question-Answer的这种形式,这里我们对Question,也就是问题进行Embedding,此处采用通义千问提供的Embedding方法。

知识库embedding:

TongYiEmbeddings embeddings = new TongYiEmbeddings();
embeddings.setServerAccessId(ALINLP_EMBEDDINGS_ACCESSID);
embeddings.setServerUrl(ALINLP_EMBEDDINGS_SERVER_URL);
embeddings.setServerUuid(ALINLP_EMBEDDINGS_UUID);
Document document = new Document();
document.setPageContent(rawText);
List<Document> documents = embeddings.embedDocument(Arrays.asList(document));
Document  vecDocument= documents.get(0);
// 向量化知识
String embeddingString = JSON.toJSONString(vecDocument.getEmbedding()).replaceAll("\\[", "{")
.replaceAll("\\]", "}");


return embeddingString;
  • 向量数据库存储和查询

此处采用hologres向量数据库,图中红框表示知识库问题与回答在数据库中具体的向量化存储数据。

9cff9d11d6d7f614f314a6093a7cd93d.png

向量距离数据库查询:

select origin_content as originContent,
        origin_title as originTitle,
        pm_approx_squared_euclidean_distance(embedding_title, #{embeddingTitle}) as distance
from vs_knowledge
order by distance asc
limit #{limit}
  • 大模型问答链路

问答chain的基本实现:

//1. 初始化ChatGLM的参数
ChatGLMV2Internal chatGLMV2Internal = new ChatGLMV2Internal();
chatGLMV2Internal.setTemperature(0.01d);
chatGLMV2Internal.setMaxLength(2048);




//2. 提示词编写
PromptTemplate prompt = new PromptTemplate();
String template = "已知信息:\n" +
"{context} \n" +
"\n" +
"根据上述已知信息,简洁和专业的来回答用户的问题。如果无法从中得到答案,请说 “根据已知信息无法回答该问题” 或 “没有提供足够的相关信息”,不允许在答案中添加编造成分,答案请使用中文。问题是:{question}";
prompt.setTemplate(template);


//3. 向量数据库检索配置,比如最大向量距离
RetrievalQA qa = new RetrievalQA();
qa.setRecommend(5);
qa.setMaxDistanceValue(10000.0d);
qa.setLlm(chatGLMV2Internal);
qa.setPrompt(prompt);
qa.setRetriever(holoRetriver.asRetriever());
qa.init();


//4. LLM大模型问答
Map<String, Object> inputs = new HashMap<>();
inputs.put("question", question);
inputs.put("input", question);
Map<String, Object> outputs = qa.run(inputs);


llmKonwledgeDO.setContent(String.valueOf(outputs.get("text")));
// 补充 doclist
return llmKonwledgeDO;
  AI Agent实践

以下实现了一个网关API调用日志解析的agent。

Agent工具注册:

this.setName("ApiLogTool");
this.setDescription("这是一个调用日志查询接口,如果[{question}]中包含requestId关键字,你可以请求这个工具与日志系统进行交互,调用这个工具。\n" +
                    "请先提取出requestId的值,将它赋值为value。调用参数:[{\"requestId\": \"value\", \"type\": \"String\", \"description\": \"调用请求id\"}]。");

工具解析:

Map<String,Object> parse = (Map<String,Object>)JSON.parse(toolInput);
if(parse.get("requestId")==null){
    return new ToolExecuteResult("");
}
String requestId = parse.get("requestId").toString();
ApiLogSearchQuery apiLogSearchQuery = new ApiLogSearchQuery();
//日志查询解析处理

思考决策逻辑:

public static final String FORMAT_INSTRUCTIONS_CH =
"用户提出了一个问题: {question} \n" +
"你可以选择使用下面这些工具:\n"+
"{tool_list_description}"+
"\n"+
"同时你的思考过程如下:"+
"Thought: 每一次你需要首先思考你应该做什么\n" +
"Action: 你需要决定是否使用工具,应该是[{tool_names}] 中的一个Action,格式为JSON。如果匹配不到工具,就不要思考了,直接返回结果,请不要把思考过程返回给用户。\n" +
"Input: 如果匹配到工具,使用的工具的输入参数,赋值给params\n" +
"Observation: 如果匹配到工具,工具的输出结果 格式为[]。\n" +
"Answer: 每一步回答问题的答案,格式为JSON。你可以多次使用Thought/Action/Input/Observation/Answer来一步一步的思考如何回答问题。\n";

1a55605bb445f179a216a1f536b1941e.png

个人小思考

  1. 未来微服务HSF这种形式会向上往 agent工厂或者agent服务框架这种形式演进,因为这个框架搭好了后,后面各个业务方快速集成到agent服务上,可被上层AI应用层调用

  2. 如果多个agent联动了,才是真正的智能

  3. 如何定义agent?

Agent体系架构可以分为慎思型、反应型和混合型。

慎思型构建负责规划和推理行为,反应型构建处理需要快速响应的重要事件。

信念-期望-意图(Belief-Desire-ltension, BDI) 体系架构是混合型体系架构的一个重要类型。Agent的表示形式,Agent的行为可以被描述成好像拥有信念、期望和意图等思维状态。信念表示Agent拥有的知识,期望描述Agent追求的目标,意图说明Agent选择计划以实现哪些目标。

64698e672bacc64446b23e1eb174e106.png

openai提供的agent概念

5f6b0d71b205a9c5978a59b61e2ca13b.png

团队介绍

我们是淘天集团商家与开放平台团队,目前主要围绕商家的日常经营场景,为中小商家提供高效易用的电商工具。

¤ 拓展阅读 ¤

3DXR技术 | 终端技术 | 音视频技术

服务端技术 | 技术质量 | 数据算法

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

有趣且重要的JS知识合集(19)前端实现图片的本地上传/截取/导出

input[file]太丑了&#xff0c;又不想去改button样式&#xff0c;那就自己实现一个上传按钮的div&#xff0c;然后点击此按钮时&#xff0c;去触发file上传的事件, 以下就是 原生js实现图片前端上传 并且按照最佳宽高比例展示图片&#xff0c;然后可以自定义截取图片&#xff0…

Unity中URP实现水效果(水的深度)

文章目录 前言一、搭建预备场景1、新建一个面片&#xff0c;使其倾斜一个角度&#xff0c;来模拟水底和岸边的效果2、随便创建几个物体&#xff0c;作为与水面接触的物体3、再新建一个面片&#xff0c;作为水面 二、开始编写水体的Shader效果1、新建一个URP基础Shader2、把水体…

redis GEO 类型原理及命令详解

目录 前言 一、GeoHash 的编码方法 二、Redis 操作GEO类型 前言 我们有一个需求是用户搜索附近的店铺&#xff0c;就是所谓的位置信息服务&#xff08;Location-Based Service&#xff0c;LBS&#xff09;的应用。这样的相关服务我们每天都在接触&#xff0c;用滴滴打车&am…

2.23通过platform总线驱动框架编写LED灯的驱动,编写应用程序测试

驱动代码 #include <linux/init.h> #include <linux/module.h> #include <linux/of_gpio.h> #include <linux/gpio.h> #include <linux/platform_device.h> #include <linux/mod_devicetable.h>#define LED_ON _IOW(l, 1, int) #define L…

nginx的功能以及运用(编译、平滑升级、提高服务器设置、location alias 等)

nginx与apache的对比 nginx优点 nginx中INPUT OUTPUT模型 零拷贝技术 原理&#xff1a;减少内核空间和用户空间的拷贝次数&#xff0c;增加INPUT OUTPUT的效率 网络I/O 模型 同步&#xff0c;异步 &#xff1a; 消息反馈机制 阻塞和非阻塞 阻塞型I/O模型&#xff1a;不利于…

第3.3章:StarRocks数据导入——Stream Load

一、概述 Stream Load是StarRocks最为核心的导入方式&#xff0c;用户通过发送HTTP请求将本地文件或数据流导入至StarRocks中&#xff0c;其本身不依赖其他组件。 Stream Load支持csv和json两种数据文件格式&#xff0c;适用于数据文件数量较少且单个文件的大小不超过10GB 的场…

[yolov9]使用python部署yolov9的onnx模型

【框架地址】 https://github.com/WongKinYiu/yolov9 【yolov9简介】 在目标检测领域&#xff0c;YOLOv9 实现了一代更比一代强&#xff0c;利用新架构和方法让传统卷积在参数利用率方面胜过了深度卷积。 继 2023 年 1 月 正式发布一年多以后&#xff0c;YOLOv9 终于来了&a…

基于Java SSM框架实现高校失物招领管理平台系统项目【项目源码】

基于java的SSM框架实现高校失物招领管理平台系统演示 B/S结构 在B/S的结构中&#xff0c;学生可以在任何可以上网的地方访问和使用系统网站的功能&#xff0c;没有地域和时间等方面的限制&#xff0c;B/S结构是把程序完整放置到计算机网络的服务器上&#xff0c;通过计算机互联…

module ‘json‘ has no attribute ‘dumps‘

如果在使用Python的json模块时遇到AttributeError: module json has no attribute dumps错误&#xff0c;通常是因为在Python环境中json模块不支持dumps方法。这种情况可能是因为Python的json模块被重命名或修改过导致的。 解决方法可以尝试以下几种&#xff1a; 1.检查Pytho…

SpringBoot:自定义starter

点击查看&#xff1a;LearnSpringBoot08starter 点击查看&#xff1a;LearnSpringBoot08starterTest 点击查看更多的SpringBoot教程 一、主要流程 1. 先创建空的project 2. 打开空的project 结构 图选中model 点击 3. 创建 model&#xff08;Maven&#xff09;启动器 提…

【C语言】内存操作,内存函数篇---memcpy,memmove,memset和memcmp内存函数的使用和模拟实现【图文详解】

欢迎来CILMY23的博客喔&#xff0c;本篇为​【C语言】内存操作&#xff0c;内存函数篇---memcpy&#xff0c;memmove&#xff0c;memset和memcmp内存函数的使用和模拟实现【图文详解】&#xff0c;图文讲解四种内存函数&#xff0c;带大家更深刻理解C语言中内存函数的操作&…

Jmeter基础(3) 发起一次请求

目录 Jmeter 一次请求添加线程组添加HTTP请求添加监听器 Jmeter 一次请求 用Jmeter进行一次请求的过程&#xff0c;需要几个步骤呢&#xff1f; 1、添加线程组2、添加HTTP请求3、添加监听器&#xff0c;查看结果树 现在就打开jmeter看下如何创建一个请求吧 添加线程组 用来…

自定义股票池策略周报告---收益1.8,回撤0.7,提供实盘设置

综合交易模型已经交易了1个月了目前收益10&#xff0c;回测0.8&#xff0c;策略追求稳稳的幸福&#xff0c;细水流长&#xff0c;回测年化20&#xff0c;最大回撤8 链接自定义股票池策略周报告---收益1.8&#xff0c;回撤0.7&#xff0c;提供实盘设置 (qq.com) 实盘稳定运行2…

ctx.drawImage的canvas绘图不清晰解决方案,以及canvas高清导出

ctx.drawImage的canvas绘图不清晰 原因&#xff1a; 查资料是这么说的&#xff1a;canvas 绘图时&#xff0c;会从两个物理像素的中间位置开始绘制并向两边扩散 0.5 个物理像素。当设备像素比为 1 时&#xff0c;一个 1px 的线条实际上占据了两个物理像素&#xff08;每个像素…

Redis篇之Redis持久化的实现

持久化即把数据保存到可以永久保存的存储设备当中&#xff08;磁盘&#xff09;。因为Redis是基于内存存储数据的&#xff0c;一旦redis实例当即数据将会全部丢失&#xff0c;所以需要有某些机制将内存中的数据持久化到磁盘以备发生宕机时能够进行恢复&#xff0c;这一过程就称…

如何将建筑白模叠加到三维地球上?

​ 通过以下方法可以将建筑白模叠加到三维地球上。 方法/步骤 下载三维地图浏览器 http://www.geosaas.com/download/map3dbrowser.exe&#xff0c;安装完成后桌面上出现”三维地图浏览器“图标。 2、双击桌面图标打开”三维地图浏览器“ 3、点击“建筑白模”菜单&…

Ubuntu20.04开启/禁用ipv6

文章目录 Ubuntu20.04开启/禁用ipv61.ipv62. 开启ipv6step1. 编辑sysctl.confstep2. 编辑网络接口配置文件 3. 禁用ipv6&#xff08;sysctl&#xff09;4. 禁用ipv6&#xff08;grub&#xff09;附&#xff1a;总结linux网络配置 Ubuntu20.04开启/禁用ipv6 1.ipv6 IP 是互联网…

面试经典150题 -- 二叉树 (总结)

总的地址 : 面试经典 150 题 - 学习计划 - 力扣&#xff08;LeetCode&#xff09;全球极客挚爱的技术成长平台 104 . 二叉树的最大深度 104 . 二叉树的最大深度 递归 : 直接用递归访问 &#xff0c; 访问左孩子 和 右孩子 &#xff0c; 如果 存在 &#xff0c; 深度就1 &…

利用R语言进行典型相关分析实战

&#x1f349;CSDN小墨&晓末:https://blog.csdn.net/jd1813346972 个人介绍: 研一&#xff5c;统计学&#xff5c;干货分享          擅长Python、Matlab、R等主流编程软件          累计十余项国家级比赛奖项&#xff0c;参与研究经费10w、40w级横向 文…

幻兽帕鲁(Palworld 1.4.1)私有服务器搭建(docker版)

文章目录 说明客户端安装服务器部署1Panel安装和配置docker服务初始化设置设置开机自启动设置镜像加速 游戏服务端部署游戏服务端参数可视化配置 Palworld连接服务器问题总结 说明 服务器硬件要求&#xff1a;Linux系统/Window系统&#xff08;x86架构&#xff0c;armbian架构…