极客时间已完结课程限时免费阅读

14|链式调用,用LangChain简化多步提示语

14|链式调用,用LangChain简化多步提示语-AI大模型之美-极客时间
下载APP

14|链式调用,用LangChain简化多步提示语

讲述:徐文浩

时长08:11大小7.47M

你好,我是徐文浩。
OpenAI 的大语言模型,只是提供了简简单单的 Completion 和 Embedding 这样两个核心接口。但是你也看到了,在过去的 13 讲里,通过合理使用这两个接口,我们完成了各种各样复杂的任务。
通过提示语(Prompt)里包含历史的聊天记录,我们能够让 AI 根据上下文正确地回答问题。
通过将 Embedding 提前索引好存起来,我们能够让 AI 根据外部知识回答问题。
而通过多轮对话,将 AI 返回的答案放在新的问题里,我们能够让 AI 帮我们给自己的代码撰写单元测试。
这些方法,也是一个实用的自然语言类应用里常见的模式。我之前也都通过代码为你演示过具体的做法。但是,如果我们每次写应用的时候,都需要自己再去 OpenAI 提供的原始 API 里做一遍,那就太麻烦了。于是,开源社区就有人将这些常见的需求和模式抽象了出来,开发了一个叫做 Langchain 的开源库。那么接下来,我们就来看看如何使用 LangChain 来快速实现之前我们利用大语言模型实现过的功能。以及我们如何进一步地,将 Langchain 和我们的业务系统整合,完成更复杂、更有实用价值的功能。

使用 Langchain 的链式调用

如果你观察得比较仔细的话,你会发现在第 11 讲我们使用 llama-index 的时候,就已经装好 LangChain 了。llama-index 专注于为大语言模型的应用构建索引,虽然 Langchain 也有类似的功能,但这一点并不是 Langchain 的主要卖点。Langchain 的第一个卖点其实就在它的名字里,也就是链式调用
我们先来看一个使用 ChatGPT 的例子,你就能理解为什么会有链式调用的需求了。我们知道,GPT-3 的基础模型里面,中文的语料很少。用中文问它问题,很多时候它回答得不好。所以有时候,我会迂回处理一下,先把中文问题给 AI,请它翻译成英文,然后再把英文问题贴进去提问,得到一个英文答案。最后,再请 AI 把英文答案翻译回中文。很多时候,问题的答案会更准确一点。比如,下面的截图里,我就请它简单介绍一下 Stable Diffusion 的原理是什么。
注:Stable Diffusion 是一个热门的开源 AI 画图工具,后面我们在介绍用 AI 生成图片的时候会用到。

人工链式调用

先让AI把中文问题翻译成英文,再直接把英文问题贴进去得到英文答案
我们再请它翻译一下英文答案
如果用 API 来实现这个过程,其实就是一个链式调用的过程。
我们先调用 OpenAI,把翻译请求和原始问题组合在一起发送给 AI,完成问题的中译英。
然后再把拿到的翻译好的英文问题发送给 OpenAI,得到英文答案。
最后再把英文答案,和对应要求 AI 翻译答案的请求组合在一起,完成答案的英译中。

使用 LLMChain 进行链式调用

如果我们用代码,可以像下面这样,一步步进行。
import openai, os
from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI
from langchain.chains import LLMChain
openai.api_key = os.environ.get("OPENAI_API_KEY")
llm = OpenAI(model_name="text-davinci-003", max_tokens=2048, temperature=0.5)
en_to_zh_prompt = PromptTemplate(
template="请把下面这句话翻译成英文: \n\n {question}?", input_variables=["question"]
)
question_prompt = PromptTemplate(
template = "{english_question}", input_variables=["english_question"]
)
zh_to_cn_prompt = PromptTemplate(
input_variables=["english_answer"],
template="请把下面这一段翻译成中文: \n\n{english_answer}?",
)
question_translate_chain = LLMChain(llm=llm, prompt=en_to_zh_prompt, output_key="english_question")
english = question_translate_chain.run(question="请你作为一个机器学习的专家,介绍一下CNN的原理。")
print(english)
qa_chain = LLMChain(llm=llm, prompt=question_prompt, output_key="english_answer")
english_answer = qa_chain.run(english_question=english)
print(english_answer)
answer_translate_chain = LLMChain(llm=llm, prompt=zh_to_cn_prompt)
answer = answer_translate_chain.run(english_answer=english_answer)
print(answer)
输出结果:
Please explain the principles of CNN as an expert in Machine Learning.
A Convolutional Neural Network (CNN) is a type of deep learning algorithm that is used to analyze visual imagery. It is modeled after the structure of the human visual cortex and is composed of multiple layers of neurons that process and extract features from an image. The main principle behind a CNN is that it uses convolutional layers to detect patterns in an image. Each convolutional layer is comprised of a set of filters that detect specific features in an image. These filters are then used to extract features from the image and create a feature map. The feature map is then passed through a pooling layer which reduces the size of the feature map and helps to identify the most important features in the image. Finally, the feature map is passed through a fully-connected layer which classifies the image and outputs the result.
卷积神经网络(CNN)是一种深度学习算法,用于分析视觉图像。它模仿人类视觉皮层的结构,由多层神经元组成,可以处理和提取图像中的特征。CNN的主要原理是使用卷积层来检测图像中的模式。每个卷积层由一组滤波器组成,可以检测图像中的特定特征。然后使用这些滤波器从图像中提取特征,并创建特征图。然后,将特征图通过池化层传递,该层可以减小特征图的大小,并有助于识别图像中最重要的特征。最后,将特征图传递给完全连接的层,该层将对图像进行分类,并输出结果。
这里的代码,我们使用了 Langchain 这个库,不过还没有动用它的链式调用过程。我们主要用了 Langchain 的三个包。
LLM,也就是我们使用哪个大语言模型,来回答我们提出的问题。在这里,我们还是使用 OpenAIChat,也就是最新放出来的 gpt-3.5-turbo 模型。
PromptTemplate,和我们在第 11 讲里看到的 llama-index 的 PromptTemplate 是一个东西。它可以定义一个提示语模版,里面能够定义一些可以动态替换的变量。比如,代码里的 question_prompt 这个模版里,我们就定义了一个叫做 question 的变量,因为我们每次问的问题都会不一样。事实上,llamd-index 里面的 PromptTemplate 就是对 Langchain 的 PromptTemplate 做了一层简单的封装。
主角 LLMChain,它的构造函数接收一个 LLM 和一个 PromptTemplate 作为参数。构造完成之后,可以直接调用里面的 run 方法,将 PromptTemplate 需要的变量,用 K=>V 对的形式传入进去。返回的结果,就是 LLM 给我们的答案。
不过如果看上面这段代码,我们似乎只是对 OpenAI 的 API 做了一层封装而已。我们构建了 3 个 LLMChain,然后按照顺序调用,每次拿到答案之后,再作为输入,交给下一个 LLM 调用。感觉好像更麻烦了,没有减少什么工作量呀?
别着急,这是因为我们还没有真正用上 LLMChain 的“链式调用”功能,而用这个功能,只需要加上一行小小的代码。我们用一个叫做 SimpleSequentialChain 的 LLMChain 类,把我们要按照顺序依次调用的三个 LLMChain 放在一个数组里,传给这个类的构造函数。
然后对于这个对象,我们调用 run 方法,把我们用中文问的问题交给它。这个时候,这个 SimpleSequentialChain,就会按照顺序开始调用 chains 这个数组参数里面包含的其他 LLMChain。并且,每一次调用的结果,会存储在这个 Chain 构造时定义的 output_key 参数里。而下一个调用的 LLMChain,里面模版内的变量如果有和之前的 output_key 名字相同的,就会用 output_key 里存入的内容替换掉模版内变量所在的占位符。
这次,我们只向这个 SimpleSequentialChain 调用一次 run 方法,把一开始的问题交给它就好了。后面根据答案去问新的问题,这个 LLMChain 会自动地链式搞定。我在这里把日志的 Verbose 模式打开了,你在输出的过程中,可以看到其实这个 LLMChain 是调用了三次,并且中间两次的返回结果你也可以一并看到。
from langchain.chains import SimpleSequentialChain
chinese_qa_chain = SimpleSequentialChain(
chains=[question_translate_chain, qa_chain, answer_translate_chain], input_key="question",
verbose=True)
answer = chinese_qa_chain.run(question="请你作为一个机器学习的专家,介绍一下CNN的原理。")
print(answer)
Verbose 日志信息:
> Entering new SimpleSequentialChain chain...
Please introduce the principle of CNN as a machine learning expert.
Convolutional Neural Networks (CNNs) are a type of artificial neural network that are commonly used in image recognition and classification tasks. They are inspired by the structure of the human brain and are composed of multiple layers of neurons connected in a specific pattern. The neurons in the first layer of a CNN are connected to the input image, and the neurons in the last layer are connected to the output. The neurons in between the input and output layers are called feature maps and are responsible for extracting features from the input image. CNNs use convolutional layers to detect patterns in the input image and pooling layers to reduce the size of the feature maps. This allows the CNN to learn the most important features in the image and use them to make predictions.
卷积神经网络(CNN)是一种常用于图像识别和分类任务的人工神经网络。它们受到人脑结构的启发,由多层神经元以特定模式连接而成。CNN的第一层神经元与输入图像连接,最后一层神经元与输出连接。输入和输出层之间的神经元称为特征映射,负责从输入图像中提取特征。CNN使用卷积层检测输入图像中的模式,使用池化层减小特征映射的大小。这使得CNN能够学习图像中最重要的特征,并利用它们进行预测。
> Finished chain.
输出结果:
卷积神经网络(CNN)是一种常用于图像识别和分类任务的人工神经网络。它们受到人脑结构的启发,由多层神经元以特定模式连接而成。CNN的第一层神经元与输入图像连接,最后一层神经元与输出连接。输入和输出层之间的神经元称为特征映射,负责从输入图像中提取特征。CNN使用卷积层检测输入图像中的模式,使用池化层减小特征映射的大小。这使得CNN能够学习图像中最重要的特征,并利用它们进行预测。
在使用这样的链式调用的时候,有一点需要注意,就是一个 LLMChain 里,所使用的 PromptTemplate 里的输入参数,之前必须在 LLMChain 里,通过 output_key 定义过。不然,这个变量没有值,程序就会报错。

支持多个变量输入的链式调用

事实上,因为使用变量的输入输出,是用这些参数定义的。所以我们不是只能用前一个 LLMChain 的输出作为后一个 LLMChain 的输入。我们完全可以连续问多个问题,然后把这些问题的答案,作为后续问题的输入来继续处理。下面我就给你看一个例子。
from langchain.chains import SequentialChain
q1_prompt = PromptTemplate(
input_variables=["year1"],
template="{year1}年的欧冠联赛的冠军是哪支球队,只说球队名称。"
)
q2_prompt = PromptTemplate(
input_variables=["year2"],
template="{year2}年的欧冠联赛的冠军是哪支球队,只说球队名称。"
)
q3_prompt = PromptTemplate(
input_variables=["team1", "team2"],
template="{team1}和{team2}哪只球队获得欧冠的次数多一些?"
)
chain1 = LLMChain(llm=llm, prompt=q1_prompt, output_key="team1")
chain2 = LLMChain(llm=llm, prompt=q2_prompt, output_key="team2")
chain3 = LLMChain(llm=llm, prompt=q3_prompt)
sequential_chain = SequentialChain(chains=[chain1, chain2, chain3], input_variables=["year1", "year2"], verbose=True)
answer = sequential_chain.run(year1=2000, year2=2010)
print(answer)
输出结果:
> Entering new SequentialChain chain...
> Finished chain.
西班牙皇家马德里队获得欧冠的次数更多,共13次,而拜仁慕尼黑只有5次。
在这个例子里,我们定义了两个 PromptTemplate 和对应的 LLMChain,各自接收一个年份作为输入,回答这两个年份的欧冠冠军。然后将两个队名作为输入,放到第三个问题里,让 AI 告诉我们这两支球队哪一支获得欧冠的次数多一些。只需要在我们的 SequentialChain 里输入两个年份,就能通过三次回答得到答案。

通过 Langchain 实现自动化撰写单元测试

看到这里,不知道你有没有想起我们上一讲刚刚讲过的通过多步提示语自动给代码写单元测试。没错,Langchain 可以顺序地通过多个 Prompt 调用 OpenAI 的 GPT 模型。这个能力拿来实现上一讲的自动化测试的功能是再合适不过的了。下面,我就拿 Langchain 重新实现了一遍上一讲的这个功能,并且给它补上了 AST 语法解析失败之后自动重试的能力。
from langchain.chains import SequentialChain
def write_unit_test(function_to_test, unit_test_package = "pytest"):
# 解释源代码的步骤
explain_code = """"# How to write great unit tests with {unit_test_package}
In this advanced tutorial for experts, we'll use Python 3.10 and `{unit_test_package}` to write a suite of unit tests to verify the behavior of the following function.
```python
{function_to_test}
```
Before writing any unit tests, let's review what each element of the function is doing exactly and what the author's intentions may have been.
- First,"""
explain_code_template = PromptTemplate(
input_variables=["unit_test_package", "function_to_test"],
template=explain_code
)
explain_code_llm = OpenAI(model_name="text-davinci-002", temperature=0.4, max_tokens=1000,
top_p=1, stop=["\n\n", "\n\t\n", "\n \n"])
explain_code_step = LLMChain(llm=explain_code_llm, prompt=explain_code_template, output_key="code_explaination")
# 创建测试计划示例的步骤
test_plan = """
A good unit test suite should aim to:
- Test the function's behavior for a wide range of possible inputs
- Test edge cases that the author may not have foreseen
- Take advantage of the features of `{unit_test_package}` to make the tests easy to write and maintain
- Be easy to read and understand, with clean code and descriptive names
- Be deterministic, so that the tests always pass or fail in the same way
`{unit_test_package}` has many convenient features that make it easy to write and maintain unit tests. We'll use them to write unit tests for the function above.
For this particular function, we'll want our unit tests to handle the following diverse scenarios (and under each scenario, we include a few examples as sub-bullets):
-"""
test_plan_template = PromptTemplate(
input_variables=["unit_test_package", "function_to_test", "code_explaination"],
template= explain_code + "{code_explaination}" + test_plan
)
test_plan_llm = OpenAI(model_name="text-davinci-002", temperature=0.4, max_tokens=1000,
top_p=1, stop=["\n\n", "\n\t\n", "\n \n"])
test_plan_step = LLMChain(llm=test_plan_llm, prompt=test_plan_template, output_key="test_plan")
# 撰写测试代码的步骤
starter_comment = "Below, each test case is represented by a tuple passed to the @pytest.mark.parametrize decorator"
prompt_to_generate_the_unit_test = """
Before going into the individual tests, let's first look at the complete suite of unit tests as a cohesive whole. We've added helpful comments to explain what each line does.
```python
import {unit_test_package} # used for our unit tests
{function_to_test}
#{starter_comment}"""
unit_test_template = PromptTemplate(
input_variables=["unit_test_package", "function_to_test", "code_explaination", "test_plan", "starter_comment"],
template= explain_code + "{code_explaination}" + test_plan + "{test_plan}" + prompt_to_generate_the_unit_test
)
unit_test_llm = OpenAI(model_name="text-davinci-002", temperature=0.4, max_tokens=1000, stop="```")
unit_test_step = LLMChain(llm=unit_test_llm, prompt=unit_test_template, output_key="unit_test")
sequential_chain = SequentialChain(chains=[explain_code_step, test_plan_step, unit_test_step],
input_variables=["unit_test_package", "function_to_test", "starter_comment"], verbose=True)
answer = sequential_chain.run(unit_test_package=unit_test_package, function_to_test=function_to_test, starter_comment=starter_comment)
return f"""#{starter_comment}""" + answer
code = """
def format_time(seconds):
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)
if hours > 0:
return f"{hours}h{minutes}min{seconds}s"
elif minutes > 0:
return f"{minutes}min{seconds}s"
else:
return f"{seconds}s"
"""
import ast
def write_unit_test_automatically(code, retry=3):
unit_test_code = write_unit_test(code)
all_code = code + unit_test_code
tried = 0
while tried < retry:
try:
ast.parse(all_code)
return all_code
except SyntaxError as e:
print(f"Syntax error in generated code: {e}")
all_code = code + write_unit_test(code)
tried += 1
print(write_unit_test_automatically(code))
输出结果:
def format_time(seconds):
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)
if hours > 0:
return f"{hours}h{minutes}min{seconds}s"
elif minutes > 0:
return f"{minutes}min{seconds}s"
else:
return f"{seconds}s"
#Below, each test case is represented by a tuple passed to the @pytest.mark.parametrize decorator.
#The first element of the tuple is the name of the test case, and the second element is a list of tuples,
#where each tuple contains the input values for the format_time() function and the expected output.
@pytest.mark.parametrize("test_case, input_values, expected_output", [
# Test cases for when the seconds parameter is an integer
("seconds is positive", (42,), "42s"),
("seconds is negative", (-42,), "-42s"),
("seconds is 0", (0,), "0s"),
# Test cases for when the seconds parameter is not an integer
("seconds is a float", (42.0,), "42.0s"),
("seconds is a string", ("42",), "42s"),
("seconds is None", (None,), "None"),
# Test cases for when the seconds parameter is an integer, but it is not in the range 0-3600
("seconds is too small", (-1,), "-1s"),
("seconds is too large", (3601,), "1h0min1s"),
])
def test_format_time(test_case, input_values, expected_output):
# We use the pytest.raises context manager to assert that the function raises a TypeError
# if the input is not an integer.
with pytest.raises(TypeError):
format_time(input_values)
# We use the pytest.approx context manager to assert that the output is approximately equal
# to the expected output, within a certain tolerance.
assert format_time(input_values) == pytest.approx(expected_output)
这个代码的具体功能,其实和上一讲是一模一样的,只是通过 Langchain 做了封装,使它更加容易维护了。我们把解释代码、生成测试计划,以及最终生成测试代码,变成了三个 LLMChain。每一步的输入,都来自上一步的输出。这个输入既包括上一步的 Prompt Template 和这一步的 Prompt Template 的组合,也包括过程中的一些变量,这些变量是上一步执行的结果作为输入变量传递进来的。最终,我们可以使用 SequentialChain 来自动地按照这三个步骤,执行 OpenAI 的 API 调用。
这整个过程通过 write_unit_test 这个函数给封装起来了。对于重试,我们则是通过一个 while 循环来调用 write_unit_test。拿到的结果和输入的代码拼装在一起,交给 AST 库做解析。如果解析通不过,则重试整个单元测试生成的过程,直到达到我们最大的重试次数为止。
LangChain 的这个分多个步骤调用 OpenAI 模型的能力,能够帮助我们通过 AI 完成复杂的任务,并且将整个任务的完成过程定义成了一个固定的流程模版。在下一讲里,我们还会进一步看到,通过这样一个链式组合多个 LLMChain 的方法,如何完成更复杂并且更具有现实意义的工作。

小结

好了,相信到这里,你脑子里应该有了更多可以利用大语言模型的好点子。这一讲,我带你学会了如何通过 Langchain 这个开源库,对大语言模型进行链式调用。想要通过大语言模型,完成一个复杂的任务,往往需要我们多次向 AI 提问,并且前面提问的答案,可能是后面问题输入的一部分。LangChain 通过将多个 LLMChain 组合成一个 SequantialChain 并顺序执行,大大简化了这类任务的开发工作。
LLMChain就是一个对大语言模型进行链式调用的模式,前面的变量和输出都可以作为下一轮调用的变量输入
Langchain 还有很多更强大的功能,我们不仅能调用语言模型,还能调用外部系统,甚至我们还能直接让 AI 做决策,决定该让我们的系统做什么。在后面的几讲里,我们会覆盖这些内容,并最终给你一个完整的电商聊天机器人。

思考题

最后,给你留一道思考题。你能试着通过 Langchain 组合多个问题,并且利用前面问题的回答结果,触发新的问题找到你想要的答案吗?欢迎你把你的例子拿出来分享在评论区,也欢迎你把这一讲分享给需要的朋友,我们下一讲再见。

推荐阅读

和之前介绍过的 llama-index 这个项目一样,Langchain 这个项目也在快速地发展和迭代过程中。我推荐你去看一看他们的官方文档,好知道他们提供的最新功能。此外,这个我们之前提到过的向量数据库公司 Pinecone,也制作了一份 Langchain AI Handbook,你也可以去看一看。

LangChain是一个开源库,通过链式调用来简化多步提示语的处理过程。文章通过使用ChatGPT的例子解释了链式调用的需求,并展示了如何使用LangChain来快速实现利用大语言模型的功能。作者介绍了LangChain的主要卖点在于链式调用,以及如何将LangChain和业务系统整合,完成更复杂、更有实用价值的功能。文章还提到了LangChain的三个包:LLM、PromptTemplate和LLMChain,以及如何使用SimpleSequentialChain实现链式调用。另外,文章还展示了如何支持多个变量输入的链式调用,通过一个例子展示了如何使用SequentialChain来处理多个问题。文章内容涉及到了OpenAI的大语言模型,以及如何利用LangChain来简化多步提示语的过程。 LangChain的主要特点在于通过链式调用来简化多步提示语的处理过程,使得利用大语言模型的功能更加便捷。文章通过具体的代码示例展示了如何使用LangChain来实现自动化撰写单元测试,以及如何通过LangChain组合多个问题,并利用前面问题的回答结果触发新的问题,从而找到所需的答案。这种链式调用的能力使得LangChain能够帮助开发者通过AI完成复杂的任务,并将整个任务的完成过程定义成一个固定的流程模板。LangChain还具有更强大的功能,不仅能调用语言模型,还能调用外部系统,甚至能直接让AI做决策,决定系统的行为。这篇文章为读者提供了对LangChain的全面介绍和实际应用示例,展示了其在简化开发工作、完成复杂任务方面的潜力。 总的来说,LangChain作为一个开源库,通过链式调用来简化多步提示语的处理过程,为开发者提供了利用大语言模型的便捷方式,同时具有丰富的功能和潜力,能够帮助开发者完成复杂的任务并简化开发工作。

分享给需要的人,Ta购买本课程,你将得20
生成海报并分享
2023-04-11

赞 32

提建议

上一篇
13 |让AI帮你写测试,体验多步提示语
下一篇
15|深入使用LLMChain,给AI连上Google和计算器
unpreview
 写留言

全部留言(18)

  • 最新
  • 精选
  • 智能
    2023-04-11 来自北京
    这种链式调用是不是很容易让问题超过token限制,有没有什么办法来自动解决这个问题

    作者回复: 链式调用,后面的步骤不是一定要包含最开头的Prompt的,根据实际情况你可以调整每个步骤实际的Prompt是什么。 目前其实Azure已经有32K Token的gpt-4-32k了,虽然贵一些。但是如果是拿来干写代码这种高价值任务我觉得还是划得来的。

    共 3 条评论
    7
  • 2023-04-11 来自广东
    老师好,看到LangChain获得1000万美元种子轮融资的新闻。 想问下:像LangChain这种开源的产品,商业模式是怎么样的,投资机构是看中了哪点进行投资的。

    作者回复: 一般都是会提供企业版来获得收入。 1. 企业版本的特有功能,比如更好的管理面板界面等等 2. 提供开源版本,也提供云端版本。云端版本托管或者按照使用量来收费 3. 给500强大企业做私有化部署、服务来收费 看中什么具体我也不知道,但是的确Langchain是现在Hacker们用得最多的一个开发框架,有用户有开发者就有可能性和未来。

    4
  • 一叶
    2023-04-11 来自福建
    老师我的想问下,国内使用Pinecone的效率如何? 会不会受到网络的影响?

    作者回复: 国内应用的话,自己部署一个postgres + pgvector 插件吧,大部分云平台应该都支持 postgres

    4
  • 厚积薄发
    2023-05-11 来自德国
    支持多个变量输入的链式调用 这个案例 多运行几次,最后的数据结果,每次都不一样 其中一次是这个‘波尔图更多,他们获得过4次欧冠冠军,而西班牙皇家马德里只获得过3次欧冠冠军。 ’ 老师,知道这个是什么原因吗?

    作者回复: 这个是大语言模型本身潜在的“幻觉”问题,本质上就是一开始的问题他回答错了。 这个解决的办法就是要用类似 Browsing 插件的方式,通过搜索路径拿到正确答案了

    共 2 条评论
    2
  • 极客雷
    2023-04-29 来自广东
    autowgpt?

    作者回复: 这个不是autogpt,只是通过langchain进行链式调用

  • 超超超超人
    2023-04-19 来自上海
    老师你好,AutoGPT 本质上是不是也使用了链式调用呢?

    作者回复: 是的,langchain也有如何实现一个autogpt的use case https://python.langchain.com/en/latest/use_cases/autonomous_agents/autogpt.html

    共 2 条评论
  • 张弛
    2023-04-14 来自中国台湾
    用ChatGPT实测本讲中提到的问题,先翻译英文提问,再翻译回来,好像并未产生更好的结果,跟直接中文提问的结果差不多。我还专门开了新的chat窗口来避免上下文影响。老师能否举个具体的通过这种方式得到更好结果的案例呢?

    作者回复: 我在直播的时候给过,中文你可以翻译过来试一下,GPT-4下中英文的推理过程和结果是不一样的。 question="""You've got to defuse a bomb by placing exactly 5 gallons of water on a sensor. The problem is, you only have a 4 gallon jug and a 3 gallons jug on hand! How can you achieve this task?"""

  • Evan
    2023-04-11 来自日本
    input_variables=["team1", "team2"], 是怎么传入参数的?

    作者回复: 这是前面两个LLMChain的ouput_key呀,是通过前面两个LLM的输出结果,再输入到这个里面的

  • Toni
    2023-04-11 来自瑞士
    part 1 (受限于2000字符,将相应的运行代码放在了part 2) 题目: 通过 Langchain 实现自动化撰写 Python 的一个函数(进行时间格式化输出),并给出对该函数的单元测试,包含对异常输入的测试。 目的: 1. 通过调用 SequentialChain 使与 ChatOpenAI 的第一次对话的结果成为第二次对话的输入,并将一,二次对话的结果显示出来,以备后续调整改进。(注: 在 ChatOpenAI 的对话窗下,ChatGPT 知道上一次对话的内容,无需重复)。 2. 使用自然语言提编程要求。 3. 通过调制 PromptTemplate 中的参数 template 来实现输出结果的最优化。这其实就是设置合适的 Prompt,以期最有效地使用 ChatGPT。 方法: 尝试着调用了 SequentialChain,使用 ChatOpenAI 的 "gpt-3.5-turbo",参数设置 temperature=1 结果: > Entering new SequentialChain chain... > Finished chain. def time_format(seconds): if seconds < 60: return f"{seconds}s" elif seconds < 3600: minutes = seconds // 60 seconds %= 60 return f"{minutes}min{seconds}s" else: hours = seconds // 3600 seconds %= 3600 minutes = seconds // 60 seconds %= 60 return f"{hours}h{minutes}min{seconds}s" > Entering new SequentialChain chain... > Finished chain. import pytest def test_time_format(): assert time_format(1) == '1s' assert time_format(61) == '1min1s' assert time_format(3678) == '1h1min18s' assert time_format(-1) == 'Invalid input' assert time_format('abc') == 'Invalid input' assert time_format(None) == 'Invalid input' assert time_format(999999) == '277h46min39s' # Add a test case for a large input As an AI language model, I cannot run this code, but I can assure you that the above code functions when used in a Python environment with the necessary dependencies and libraries installed. 结论: 输出基本满足了设计要求。ChatGPT3.5 在编程方面有所表现,尤其是考虑到本例中使用的模型是 gpt-3.5-turbo。
    展开
    共 2 条评论
    2
  • Toni
    2023-04-11 来自瑞士
    part 2 在 part 1 中使用的代码如下: import openai, os from langchain.chat_models import ChatOpenAI #from langchain.llms import OpenAI from langchain.prompts import PromptTemplate from langchain.chains import LLMChain from langchain.chains import SequentialChain openai.api_key = os.environ.get("OPENAI_API_KEY") llm = ChatOpenAI(model_name="gpt-3.5-turbo", max_tokens=2048, temperature=1) #text-davinci-003, 2048, max_tokens: 4096 for gpt-3.5-turbo Q1_prompt = PromptTemplate( template="用Python写一个函数,进行时间格式化输出,要求仅需要格式化到小时(?h?min?s)。比如:{Q1}", input_variables=["Q1"] ) Q2_prompt = PromptTemplate( # template="请为程序{A1}用'pytest' 写一个单元测试", template="""请为程序{A1}用'pytest' 写一个单元测试, Besides the test that counts negative numbers, include test cases like the input string "abc", and any other test cases you can think of, 将所有的 Test Cases 写入同一个测试中""", input_variables=["A1"] ) chain1 = LLMChain(llm=llm, prompt=Q1_prompt, output_key="A1") chain2 = LLMChain(llm=llm, prompt=Q2_prompt, output_key="A2") q1=""" 输入 输出 1 1s 61 1min1s """ sequential_chain_p1 = SequentialChain(chains=[chain1], input_variables=["Q1"], verbose=True) answer1 = sequential_chain_p1.run(Q1=q1) print(answer1) sequential_chain_p2 = SequentialChain(chains=[chain1, chain2], input_variables=["Q1"], verbose=True) answer2 = sequential_chain_p2.run(Q1=q1) print(answer2) ----------- ----------- 如何将代码封装在一个 App 中呢? 未来的程序辅助设计是沿这个思路走还是另辟蹊径? 如果有了用户交互界面,如何控制生成的程序不自己乱跑,亦或 '在正确使用的引导下' 让自动又自动生成的程序跑出了 '天际',使得让人百思不得其解的事,豁然开朗了起来。 解了一题留下了更多问题。
    展开
    1