用 100 行代码揭开 LLM 集成工具 LangChain 的神秘之处!

3c8f42bfe28bb3eed192c7bb26c69884.gif

整理 | 王子彧    责编 | 梦依丹 

出品 | CSDN(ID:CSDNnews)

LangChain 是一个强大的程序框架,它允许用户围绕大型语言模型快速构建应用程序和管道。它直接与 OpenAI 的 GPT-3 和 GPT-3.5 模型以及 Hugging Face 的开源替代品(如 Google 的 flan-t5 模型)集成。除此之外,它还提供了一套工具、组件和接口,可简化创建由大型语言模型 ( LLM ) 和聊天模型提供支持的应用程序的过程。LangChain 可以轻松管理与语言模型的交互,将多个组件链接在一起,并集成额外的资源,例如 API 和数据库。开发者可以借助它轻松打造自己的 AI 知识库。

da77c7116285142b838280ead8aac32d.png

时至今日,LLMs 接口框架 LangChain 在 GitHub 上已经收获了 3万+ 个 Star,已经成为了当下非常流行的一个工具包。

5 月 4 日,Scott Logic 首席技术官 Colin Eberhardt 发表了一篇博文。他表示,自己用 100 行代码重新来研究 LangChain,揭示了 LangChain 背后的工作原理。

2e86085a4e084a611b79ce1c1b88c9ec.png

LangChain 主要问题循环

Colin Eberhardt 表示,他最感兴趣的 LangChain 部分是其 Agent 模型。这个 API 允许你创建复杂的对话接口,并且利用各种工具(例如 Google 搜索、计算器)来回答问题。因此,成功解决了在用 LLM 回答重要问题时,所遇到的产生错误答案的倾向和缺乏最新数据等问题。

从广义上讲,使用 Agent 模型,让 LLM 成为了一个编排器。接受问题,将其分解为块,然后使用适当的工具来组合答案。

深入研究 LangChain 代码库,可以发现该流程是通过以下提示执行的:

Answer the following questions as best you can. You have access to the following tools:search: a search engine. useful for when you need to answer questions about currentevents. input should be a search query.
calculator: useful for getting the result of a math expression. The input to thistool should be a valid mathematical expression that could be executedby a simple calculator.Use the following format:Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [search, calculator]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input questionBegin!Question: ${question}
Thought:

提示分为几个部分:

  1. 明确表达总体目标“回答以下问题......”

  2. 工具列表,并简要说明其功能

  3. 用于解决问题的步骤,可能涉及迭代

  4. 问题。接下来是第一个问题,这是 GPT 将开始添加文本的位置(即完成)

Colin Eberhardt 认为第 3 部分特别有趣,它是通过一个示例(即一次性学习)“教”GPT 来充当编排器的地方。这里教的编排方法是通过思维链进行推理,将问题分解为更小的组件。研究人员发现这些组件能够提供更好的结果,并且符合推理逻辑。

这就是提示设计的艺术!

根据提示,让以下代码通过 OpenAI API 把上述提示与关于“昨天旧金山的最高温达到多少华氏度?”问题发送到 GPT-3.5:

import fs from "fs";// construct the prompt, using our question
const prompt = fs.readFileSync("prompt.txt", "utf8");
const question = "What was the high temperature in SF yesterday in Fahrenheit?";
const promptWithQuestion = prompt.replace("${question}", question);// use GPT-3.5 to answer the question
const completePrompt = async (prompt) =>await fetch("https://api.openai.com/v1/completions", {method: "POST",headers: {"Content-Type": "application/json",Authorization: "Bearer " + process.env.OPENAI_API_KEY,},body: JSON.stringify({model: "text-davinci-003",prompt,max_tokens: 256,temperature: 0.7,stream: false,}),}).then((res) => res.json());.then((res) => res.choices[0].text);const response = await completePrompt(promptWithQuestion);
console.log(response.choices[0].text);

得到的结果如下:

Question: What was the high temperature in SF yesterday in Fahrenheit?
Thought: I can try searching the answer
Action: search
Action Input: "high temperature san francisco yesterday fahrenheit"
Observation: Found an article from the San Francisco Chronicle forecastinga high of 69 degrees
Thought: I can use this to determine the answer
Final Answer: The high temperature in SF yesterday was 69 degrees Fahrenheit.

可以看到 GPT 已经确定了执行步骤,即应该执行搜索,使用“昨日旧金山高温华氏度”这个术语。但有意思的是,它已经提前预测出了搜索结果,给出了 69 °F 的答案。

令人印象深刻的是,仅仅通过简单的提示,GPT 就已经“推理”了回答这个问题的最佳方法。如果你只是直接问GPT :“昨天旧金山高温是多少?”,它会回答:”对我来说,昨天( 2019 年 8 月 28 日)旧金山的高温是 76 °F。显然,这不是昨天,但该日期报告的温度却是正确的!

因此,为了防止 GPT 想象整个对话,我们只需要指定一个停止序列即可。

384908c5604bf9c81ef4909d32409f21.png

搜索工具

在正确的位置完成停止后,现在需要创建第一个“工具”,它执行 Google 搜索。Colin Eberhardt 将使用 SerpApi 来爬取 Google,并以简单的 SON 格式提供响应。

下面对工具进行定义,命名为:search

const googleSearch = async (question) =>await fetch(`https://serpapi.com/search?api_key=${process.env.SERPAPI_API_KEY}&q=${question}`).then((res) => res.json()).then((res) => res.answer_box?.answer || res.answer_box?.snippet);const tools = {search: {description:`a search engine. useful for when you need to answer questions aboutcurrent events. input should be a search query.`,execute: googleSearch,},
};

该函数使用 SerpApi,在这种情况下,主要依赖通过页面的“答案框”组件可见的结果。这是让谷歌提供答案而不仅仅是网页结果列表的一种巧妙方法。

接下来,将更新提示模板以动态添加工具:

let prompt = promptTemplate.replace("${question}", question).replace("${tools}",Object.keys(tools).map((toolname) => `${toolname}: ${tools[toolname].description}`).join("\n"));

Colin Eberhardt 想要根据给定的迭代执行工具,将结果附加到提示中。此过程将持续,直到 LLM 协调器确定它有足够的信息并返回。

const answerQuestion = async (question) => {let prompt = // ... see above// allow the LLM to iterate until it finds a final answerwhile (true) {const response = await completePrompt(prompt);// add this to the promptprompt += response;const action = response.match(/Action: (.*)/)?.[1];if (action) {// execute the action specified by the LLMsconst actionInput = response.match(/Action Input: "?(.*)"?/)?.[1];const result = await tools[action.trim()].execute(actionInput);prompt += `Observation: ${result}\n`;} else {return response.match(/Final Answer: (.*)/)?.[1];}}
};

下一步:

const answer = awaitanswerQuestion("What was the temperature in Newcastle (England) yesterday?")
console.log(answer)

当 Colin Eberhardt 运行上述代码时,它给出的答案是“昨天纽卡斯尔(英格兰)的最高温度是 56°F,最低温度是 46°F”,完全正确。

通过查看提示迭代增长,可以看到工具调用链:

Question: what was the temperature in Newcastle (England) yesterday?
Thought: This requires looking up current information about the weather.
Action: search
Action Input: "Newcastle (England) temperature yesterday"
Observation: Newcastle Temperature Yesterday. Maximum temperature yesterday:56 °F (at 6:00 pm) Minimum temperature yesterday: 46 °F(at 11:00 pm) Average temperature ...
Final Answer: The maximum temperature in Newcastle (England) yesterday was 56°Fand the minimum temperature was 46°F.

它成功地调用了搜索工具,并且从结果观察中确定它有足够的信息并能给出一个汇总的响应。

e2dc5052d254a770f9750c4f5062d5e7.png

计算器工具

Colin Eberhardt 认为可以通过添加计算器工具来使其更强大:

import { Parser } from "expr-eval";const tools = {search: { ... },calculator: {description:`Useful for getting the result of a math expression. The input to thistool should be a valid mathematical expression that could be executedby a simple calculator.`,execute: (input) => Parser.evaluate(input).toString(),},
};

使用 expr-eval 模块完成所有复杂工作,这是一个简单的添加,现在可以做一些数学运算。同样,需要再次查看提示来了解内部工作原理,而不仅仅是查看结果:

Question: what is the square root of 25?
Thought: I need to use a calculator for this
Action: calculator
Action Input: 25^(1/2)
Observation: 5
Thought: I now know the final answer
Final Answer: The square root of 25 is 5.

在这里,LLM 已成功确定这个问题需要计算器。它还发现,对于计算器来说,“ 25 的平方根”通常表示为“25^(1/2)”,从而达到预期的结果。

当然,现在可以提出需要同时搜索网络和计算的问题。当被问及“昨天旧金山高温是多少华氏度?或者是多少摄氏度?“它能正确回答,”昨天,旧金山的高温是 54°F 或 12.2° C。

让我们看看它是如何实现这一点的:

Question: What was the high temperature in SF yesterday in Fahrenheit? And the same value in celsius?
Thought: I need to find the temperature for yesterday
Action: search
Action Input: "High temperature in San Francisco yesterday" 
Observation: San Francisco Weather History for the Previous 24 Hours ; 54 °F · 54 °F
Thought: I should convert to celsius
Action: calculator
Action Input: (54-32)*5/9
Observation: 12.222222222222221
Thought: I now know the final answer
Final Answer: Yesterday, the high temperature in SF was 54°F or 12.2°C.

在第一次迭代中,它像以前一样执行 Google  搜索。但它没有给出最终答案,而是推断它需要将这个温度转换为摄氏度。有趣的是,LLM已经知道这种转换的公式,使它能够立即应用计算器。最终答案被正确地总结——请注意摄氏值合理进行了四舍五入。

这里仅有约 80 行代码,但实现的功能让人印象深刻。Colin Eberhardt 表示,我们可以做到的远不止于此。

b2464f15c62b123d85c8c7cabd0cdd7b.png

对话界面

当前版本的代码只回答了一个问题。在上面的例子中,Colin Eberhardt 表示必须将两个问题绑定在一句话中。因此,更好的界面应该是对话形式的,能够允许用户在保留上下文的同时提出后续问题(即不要忘记对话中的先前步骤)。

如何用 GPT 实现这一点并不明显,交互是无状态的,您提供提示,模型提供完成。创建一个长时间的对话需要一些非常聪明的提示工程。深入研究 LangChain 后,我发现它使用了一种有趣的技术。

以下提示采用聊天历史记录和后续问题,要求 GPT 将问题改写为独立问题:

Given the following conversation and a follow up question, rephrase the
follow up question to be a standalone question.
Chat History:
${history}
Follow Up Input: ${question}
Standalone question:

以下代码使用之前的函数,将其包装在允许持续对话的进一步循环中。每次迭代时,聊天记录都会附加到“日志”中,并根据上述提示来确保每个后续问题都可以作为独立问题工作。

const mergeTemplate = fs.readFileSync("merge.txt", "utf8");// merge the chat history with a new question
const mergeHistory = async (question, history) => {const prompt = mergeTemplate.replace("${question}", question).replace("${history}", history);return await completePrompt(prompt);
};// main loop - answer the user's questions
let history = "";
while (true) {const question = await rl.question("How can I help? ");if (history.length > 0) {question = await mergeHistory(question, history);}const answer = await answerQuestion(question);console.log(answer);history += `Q:${question}\nA:${answer}\n`;
}

如何将这个合并过程应用于之前的例子中?用户首先问“昨日旧金山的最高温度是多少华氏度?”然后问“是多少摄氏度?”。

当被问及第一个问题时,LLM 编排器搜索了谷歌并回答“昨天,旧金山的高温为 54°F ”。这就是聊天记录的合并方式,以使后续问题成为独立问题:

Given the following conversation and a follow up question, rephrase the
follow up question to be a standalone question.
Chat History:
Q: What was the high temperature in SF yesterday in Fahrenheit?
A: Yesterday, the high temperature in SF was 54°F
Follow Up Input: what is that in celsius?
Standalone question:

通过上述提示,GPT 回答了“ 54°F 是多少摄氏度?”,这正是 Colin Eberhardt 想要的——对原始问题的修改,以包含聊天历史记录中的重要上下文。综上所述,对话的流程如下:

Q: What was the high temperature in SF yesterday in Fahrenheit?
Yesterday, the high temperature in SF was 54°F
Q: What is that in celsius?
53°F is equal to 11.6°C

现在有了一个由 LLM 编排的对话界面,它使用其推理功能来适当地使用工具,所有这些都只需 100 行代码。

4b5cd3c41fa7773f5d39136cf6096b9b.png

一些好的例子

以下是一些对话示例:

Q: What is the world record for solving a rubiks cube?
The world record for solving a Rubik's Cube is 4.69 seconds, held by Yiheng
Wang (China).
Q: Can a robot solve it faster?
The fastest time a robot has solved a Rubik's Cube is 0.637 seconds.
Q: Who made this robot?
Infineon created the robot that solved a Rubik's Cube in 0.637 seconds.
Q: What time would an average human expect for solving?
It takes the average person about three hours to solve a Rubik's cube for the
first time.

Colin Eberhardt 表示,深入研究这些问题背后的推理逻辑很有意思。在这个示例中,搜索工具返回结果,但由于某种原因,LLM 决定需要确认答案,使用稍微修改过的查询。

Question:  What is the fastest time a robot has solved a Rubik's Cube?
Thought: I should research this online
Action: search
Action Input: fastest time a robot solved Rubik's Cube
Observation: 0.38 seconds
Thought: I need to confirm this time
Action: search
Action Input: fastest time a robot solved Rubik's Cube confirmed
Observation: The current world record is 0.637 seconds, which was set by
German engineer Albert Beer and his robot Sub1 Reloaded.
The researchers realised they could solve the cube more quickly by using
a different type of motor in their robot.

那流行文化呢?以下是 Colin Eberhardt 关于漫威电影的简短聊天:

Q: Which is the best MCU film?
According to critics, the best MCU film is Avengers: Endgame (2019).
Q: What is the plot outline?
After Thanos decimates the planet and universe, the remaining Avengers must
figure out a way to bring back their vanquished allies for an epic showdown
with Thanos.
Q: Which avengers die in this film?
Tony Stark, Black Widow, Vision, and Thanos died in Avengers: Endgame (2019).
Q: Is thanos an avenger now?!
No, Thanos is not an Avenger in Avengers: Endgame (2019).
Q: So your last answer was wrong? only three avengers died.
8 Avengers died in Avengers: Endgame (2019).
^H^H^H^H

如你所见,它很快就会开始给出相互矛盾的答案!

401417c045f5181bbd6da4878ec5991f.png

结论

Colin Eberhardt 表示,他十分享受这个过程,并学到了很多关于将调用 LLM 来链的整体概念。并且他认为操作起来十分简单,尤其是核心编排/推理,只需给模型一个例子,它就可以运行。

但是,Colin Eberhardt 也意识到了它在当下存在的弱点。因为 Colin Eberhardt 提供的示例都是正常情况,当遇到特殊情况时,它就不能 100% 的工作,因此不得不经常调整问题才能达到所需的结果。

LangChain 也是如此。了解背后的工作原理,能够有助于解决特殊问题。例如,有时 LLM 编排器只是决定它不需要使用计算器,可以自己执行给定的计算。

Colin Eberhardt 表示,希望每一个使用这个工具的人都能了解其背后的原理。它是对精心设计提示的抽象,但这些提示并不完美。用美国软件工程师 Joel Spolsky 话来说,这种抽象在某些地方存在一些漏洞。

参考文献:

https://blog.scottlogic.com/2023/05/04/langchain-mini.html

推荐阅读:

▶启航!2023 Amazon DeepRacer 自动驾驶赛车中国联赛战燃擎开启!

▶ “我在 iPhone 上,创建了个 ChatGPT 快捷方式,这也太万能了……”

▶谷歌内部文件泄露:我们和 OpenAI 都赢不了,因为正被“开源”偷家!

775b2f4ad5200be5c81d3a5cf5e439f4.jpeg

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

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

相关文章

The missing quarter of a million 消失的25万 | 经济学人20230311版社论高质量双语精翻

文 / 柳下婴(微信公众号:王不留) 本期我们选择的是3月11日《经济学人》周报封面文章,即社论区(Leaders)的首篇文章:《25万英国人消失之谜》(“The missing quarter of a million”&a…

哈佛计算机系王牌项目,要请AI来当导师了

克雷西 发自 凹非寺量子位 | 公众号 QbitAI 近日,哈佛宣布了一个重磅决定:AI导师将进入课程。 负责的还是计算机系的旗舰项目——计算机科学导论,也就是著名的CS50。 借助机器人导师,哈佛的CS50项目将拥有1:1的师生比。 这一消息是…

哈佛计算机系王牌项目,要请AI来当导师了!

来源 | 量子位 作者 | 克雷西 近日,哈佛宣布了一个重磅决定:AI导师将进入课程。负责的还是计算机系的旗舰项目——计算机科学导论,也就是著名的CS50。借助机器人导师,哈佛的CS50项目将拥有1:1的师生比。 这一消息是CS50项目导师Da…

机器学习吴恩达课程总结(一)

文章目录 1. 第一章 简介1.1 机器学习(Machine Learning)1.2 有监督学习(Supervised Learning)1.3 无监督学习(Unsupervised Learning) 2. 第二章 线性回归(Linear Regression)2.1 假…

吴恩达NLP课程资料

NLP_wuenda 1.简介 吴恩达老师在2020年6月份推出了NLP课程,Natural Language Processing Specialization  本人忙里偷闲将老师的视频和作业都完成了,后续会持续更新课程的资料和作业。目前NLP课程一共分为四门,每门课程会分为三&#xff08…

吴恩达新课程:ChatGPT提示工程,ChatGPT Prompt Engineering for Developers

来源:专知 本文为课程介绍,建议阅读5分钟 您将学习如何使用大型语言模型(LLM)快速构建新的和强大的应用程序。 https://learn.deeplearning.ai/chatgpt-prompt-eng/lesson/1/introduction 在ChatGPT Prompt Engineering for Developers中,您将…

python 用户登录,密码错误3次则锁定该用户

需求: 输入用户名密码 认证成功后显示欢迎信息 输错三次后锁定 实现思路: 判断用户是否在黑名单,如果在黑名单提示账号锁定,然后退出操作。 判断账号密码是否正确,如果正确则正常登录。如果不正确有三次输入密码机会…

Git 密码输入错误解决方案

前言:有时候我们不小心输入了密码,想要重新输入一次,但是始终找不到重新输入的提示框,这是因为 Windows缓存了我们的Git账号密码作为凭证,帮助我们下次自动登录 修改Git凭证 总结:控制面板 -> 用户账户…

使用git时输错密码解决办法

在使用git在clone项目的时候出现了让输入用户名和密码,然而密码输入错误导致项目clone不下来.. 解决办法:找到在控制面板\用户帐户\凭据管理器\windows凭据\ 里面删除原来的密码,删除后就可以重新输入密码了 输入正确的密码就可以clone了

Linux中标麒麟操作系统下,多次密码输入错误后账户被锁定的解决方法

错误描述 账户在登陆时,输入密码错误次数超过限制,账户就会被锁定。此后,即使密码输入正确,也不能正常登陆。 解决方法 1、使用root账号登陆系统 root账号需要点击“未列出”,在出现的提示框中输入root,…

关于密码输错三次后锁定登录

前言 用户登录输错密码三次将自动锁定该用户,本章用mybatisplus 提示:以下是本篇文章正文内容,下面案例可供参考 一、数据库展示 数据库字段展示 erroeNum为错误次数,isLock:0未锁定,1:锁定…

linux(ubuntu)用户连续N次输入错误密码进行登陆时,自动锁定X分钟

1、编辑PAM的配置文件 sudo vim /etc/pam.d/login在第二行添加 auth required pam_tally2.so deny3 unlock_time5 even_deny_root root_unlock_time10参数介绍 even_deny_root 也限制root用户; deny 设置普通用户和root用户连续错误登陆的最大次…

用户正确输入密码会累计错误次数,累计5次后用户锁定

问题描述 提示:遇到的问题: 安全要求用户密码输入错误5次,锁定用户600秒 ,安全加固后,反馈openssh后登录pam_tally2.so计数不清零问题,用户输入正确密码pam_tall2依旧会增加错误次数 解决方案: …

Ubuntu用户连续N次输入错误密码进行登陆时自动锁定X分钟

1、编辑PAM的配置文件 sudo vim /etc/pam.d/login在第二行添加 auth required pam_tally2.so deny=3 unlock_time=5 even_deny_root root_unlock_time=10参数介绍 even_deny_root 也限制root用户; deny 设置普通用户和root用户连续错误登陆的最大次数,超过最大次数,则锁…

Git Bash输错账号密码如何重新输入

很多时候我们容易在Git Bash操作的时候,不慎输入错误的用户名或密码,此时一直提示: remote: Incorrect username or password ( access token ) 解决办法: 1.打开控制面板(快捷打开winR,输入control) 2.…

在git上输错密码,解救办法

当输入密码错误后,git会把密码保存在windows的你的当前用户名的缓存中。 我们可以在控制面板中寻找到这个缓存,再删掉就可以了。 首先,打开“控制面板”,再打开“用户账户” 点击管理你的凭据, 在点击windows凭据&am…

windows中git输错密码后不能重新输入的问题

当输入密码错误后,git会把密码保存在windows的你的当前用户名的缓存中。 我们可以在控制面板中寻找到这个缓存,再删掉就可以了。 首先,打开“控制面板”,把“查看方式”改为“大图标”,再打开“用户账户” 会打开“用…

gitHub不能用密码推送了,必须要使用令牌

有一段时间没使用github去push项目了,今天push之后,根据提示输入账号密码,但是失败了,报错如下: support for password authentication was removed on August 13, 2021. remote: Please see https://docs.github.com…

【Linux】Ubuntu登录账户时多次输错密码锁定账户策略

一、编辑PAM的配置文件 vim /etc/pam.d/sshd (ssh远程登录) vim /etc/pam.d/login (终端窗口登录) 二、在第二行添加 只设置普通用户 auth required pam_tally2.so deny3 unlock_time5 设置普通用户和root用户 auth required pam_tally2.so de…

ChatGPT Prompt实战技巧——Prompt提示词生成器

很多时候,我们不知道去写出一个非常好的提示词,这个时候我们为什么不让ChatGPT提供帮助呢? 简单地说,就是让ChatGPT扮演一个提示词生成专家,帮助你完成/完善/改进你的prompt。 让ChatGPT帮你写提示词,然后…