少量样本示例的提示模板 – LangChain中文网

6大核心模块（Modules)提示工程（Prompts)提示模板（Prompt Templates）示例（Examples）少量样例（Few-Shot Examples）

少量样本示例的提示模板
在本教程中，我们将学习如何创建使用少量样本示例的提示模板。
我们将使用
```code
FewShotPromptTemplate
```
类来创建使用少量样本示例的提示模板。此类要么接受一组示例，要么接受一个
```code
ExampleSelector
```
对象。在本教程中，我们将介绍这两个选项。
用例#
在本教程中，我们将为自我提问与搜索配置少量样本示例。
使用示例集#
创建示例集#
首先，创建少量样本示例列表。每个示例应该是一个字典，键是输入变量，值是这些输入变量的值。

```code
from langchain.prompts.few_shot import FewShotPromptTemplate
from langchain.prompts.prompt import PromptTemplate

examples = [
{
"question": "Who lived longer, Muhammad Ali or Alan Turing?",
"answer":
"""
Are follow up questions needed here: Yes.
Follow up: How old was Muhammad Ali when he died?
Intermediate answer: Muhammad Ali was 74 years old when he died.
Follow up: How old was Alan Turing when he died?
Intermediate answer: Alan Turing was 41 years old when he died.
So the final answer is: Muhammad Ali
"""
},
{
"question": "When was the founder of craigslist born?",
"answer":
"""
Are follow up questions needed here: Yes.
Follow up: Who was the founder of craigslist?
Intermediate answer: Craigslist was founded by Craig Newmark.
Follow up: When was Craig Newmark born?
Intermediate answer: Craig Newmark was born on December 6, 1952.
So the final answer is: December 6, 1952
"""
},
{
"question": "Who was the maternal grandfather of George Washington?",
"answer":
"""
Are follow up questions needed here: Yes.
Follow up: Who was the mother of George Washington?
Intermediate answer: The mother of George Washington was Mary Ball Washington.
Follow up: Who was the father of Mary Ball Washington?
Intermediate answer: The father of Mary Ball Washington was Joseph Ball.
So the final answer is: Joseph Ball
"""
},
{
"question": "Are both the directors of Jaws and Casino Royale from the same country?",
"answer":
"""
Are follow up questions needed here: Yes.
Follow up: Who is the director of Jaws?
Intermediate Answer: The director of Jaws is Steven Spielberg.
Follow up: Where is Steven Spielberg from?
Intermediate Answer: The United States.
Follow up: Who is the director of Casino Royale?
Intermediate Answer: The director of Casino Royale is Martin Campbell.
Follow up: Where is Martin Campbell from?
Intermediate Answer: New Zealand.
So the final answer is: No
"""
}
]

```

创建Few-shot示例的格式化程序#
配置一个格式化程序，将Few-shot示例格式化为字符串。这个格式化程序应该是一个
```code
PromptTemplate
```
对象。

```code
example_prompt = PromptTemplate(input_variables=["question", "answer"], template="Question: {question}\n{answer}")

print(example_prompt.format(**examples[0]))

```

```code
Question: Who lived longer, Muhammad Ali or Alan Turing?

Are follow up questions needed here: Yes.
Follow up: How old was Muhammad Ali when he died?
Intermediate answer: Muhammad Ali was 74 years old when he died.
Follow up: How old was Alan Turing when he died?
Intermediate answer: Alan Turing was 41 years old when he died.
So the final answer is: Muhammad Ali

```

```code
FewShotPromptTemplate
```
#
最后，创建一个
```code
FewShotPromptTemplate
```
对象。这个对象接受Few-shot示例和Few-shot示例格式化程序。

```code
prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=example_prompt,
suffix="Question: {input}",
input_variables=["input"]
)

print(prompt.format(input="Who was the father of Mary Ball Washington?"))

```

```code
Question: Who lived longer, Muhammad Ali or Alan Turing?

Are follow up questions needed here: Yes.
Follow up: How old was Muhammad Ali when he died?
Intermediate answer: Muhammad Ali was 74 years old when he died.
Follow up: How old was Alan Turing when he died?
Intermediate answer: Alan Turing was 41 years old when he died.
So the final answer is: Muhammad Ali

Question: When was the founder of craigslist born?

Are follow up questions needed here: Yes.
Follow up: Who was the founder of craigslist?
Intermediate answer: Craigslist was founded by Craig Newmark.
Follow up: When was Craig Newmark born?
Intermediate answer: Craig Newmark was born on December 6, 1952.
So the final answer is: December 6, 1952

Question: Who was the maternal grandfather of George Washington?

Are follow up questions needed here: Yes.
Follow up: Who was the mother of George Washington?
Intermediate answer: The mother of George Washington was Mary Ball Washington.
Follow up: Who was the father of Mary Ball Washington?
Intermediate answer: The father of Mary Ball Washington was Joseph Ball.
So the final answer is: Joseph Ball

Question: Are both the directors of Jaws and Casino Royale from the same country?

Are follow up questions needed here: Yes.
Follow up: Who is the director of Jaws?
Intermediate Answer: The director of Jaws is Steven Spielberg.
Follow up: Where is Steven Spielberg from?
Intermediate Answer: The United States.
Follow up: Who is the director of Casino Royale?
Intermediate Answer: The director of Casino Royale is Martin Campbell.
Follow up: Where is Martin Campbell from?
Intermediate Answer: New Zealand.
So the final answer is: No

Question: Who was the father of Mary Ball Washington?

```

使用举例选择器 Using an example selector#
给
```code
ExampleSelector
```
传入举例 #
我们将重用前一节中的示例集和格式化程序。
但是，我们将不直接将示例馈送到
```code
FewShotPromptTemplate
```
对象中，而是将其馈送到
```code
ExampleSelector
```
对象中。
在本教程中，我们将使用
```code
SemanticSimilarityExampleSelector
```
类。
该类基于输入的相似性选择few shot示例。它使用嵌入模型计算输入和few shot示例之间的相似性，以及向量存储库执行最近邻搜索。

```code
from langchain.prompts.example_selector import SemanticSimilarityExampleSelector
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings

example_selector = SemanticSimilarityExampleSelector.from_examples(
# This is the list of examples available to select from.
examples,
# This is the embedding class used to produce embeddings which are used to measure semantic similarity.
OpenAIEmbeddings(),
# This is the VectorStore class that is used to store the embeddings and do a similarity search over.
Chroma,
# This is the number of examples to produce.
k=1
)

# Select the most similar example to the input.
question = "Who was the father of Mary Ball Washington?"
selected_examples = example_selector.select_examples({"question": question})
print(f"Examples most similar to the input: {question}")
for example in selected_examples:
print("\n")
for k, v in example.items():
print(f"{k}: {v}")

```

```code
Running Chroma using direct local API.
Using DuckDB in-memory for database. Data will be transient.
Examples most similar to the input: Who was the father of Mary Ball Washington?

question: Who was the maternal grandfather of George Washington?
answer:
Are follow up questions needed here: Yes.
Follow up: Who was the mother of George Washington?
Intermediate answer: The mother of George Washington was Mary Ball Washington.
Follow up: Who was the father of Mary Ball Washington?
Intermediate answer: The father of Mary Ball Washington was Joseph Ball.
So the final answer is: Joseph Ball

```

将示例选择器馈送到
```code
FewShotPromptTemplate
```
#
最后，创建一个
```code
FewShotPromptTemplate
```
对象。该对象接受示例选择器和few shot示例的格式化程序。

```code
prompt = FewShotPromptTemplate(
example_selector=example_selector,
example_prompt=example_prompt,
suffix="Question: {input}",
input_variables=["input"]
)

print(prompt.format(input="Who was the father of Mary Ball Washington?"))

```

```code
Question: Who was the maternal grandfather of George Washington?

Are follow up questions needed here: Yes.
Follow up: Who was the mother of George Washington?
Intermediate answer: The mother of George Washington was Mary Ball Washington.
Follow up: Who was the father of Mary Ball Washington?
Intermediate answer: The father of Mary Ball Washington was Joseph Ball.
So the final answer is: Joseph Ball

Question: Who was the father of Mary Ball Washington?

```
自定义提示模板（Custom Prompt Template）部分（Partial）


部分格式化提示模板 – LangChain中文网

6大核心模块（Modules)提示工程（Prompts)提示模板（Prompt Templates）示例（Examples）部分（Partial）

部分格式化提示模板
提示模板是具有
```code
.format
```
方法的类，该方法接受键-值映射并返回字符串（提示)，以传递给语言模型。
与其他方法一样，“部分”提示模板可能有意义——例如，传入所需值的子集，以创建仅期望剩余值子集的新提示模板。
LangChain以两种方式支持此功能：我们允许
（1)带有字符串值的部分格式化的提示，
（2)带有返回字符串值的函数的部分格式化提示。
这两种不同的方式支持不同的用例。在下面的文档中，我们讨论了两种用例的动机以及如何在LangChain中进行操作。
使用字符串进行部分格式化
部分提示模板的一个常见用例是，如果您先获取某些变量而不是其他变量，那么您可能需要部分提示模板。
例如，假设您有一个需要两个变量foo和baz的提示模板。如果您在链条的早期获取了foo值，但稍后才获取了baz值，那么等到在一个地方同时拥有两个变量才将它们传递给提示模板可能会很麻烦。相反，您可以使用foo值部分化提示模板，然后将部分化的提示模板传递下去，只需使用它即可。以下是执行此操作的示例：

```code
from langchain.prompts import PromptTemplate

```

```code
prompt = PromptTemplate(template="{foo}{bar}", input_variables=["foo", "bar"])
partial_prompt = prompt.partial(foo="foo");
print(partial_prompt.format(bar="baz"))

```

```code
foobaz

```

你也可以只使用部分变量初始化Prompt。

```code
prompt = PromptTemplate(template="{foo}{bar}", input_variables=["bar"], partial_variables={"foo": "foo"})
print(prompt.format(bar="baz"))

```

```code
foobaz

```

函数部分化Partial With Functions#
另一个常见的用途是使用函数部分化。这种情况的用例是当您知道您总是想以一种常见的方式获取一个变量时。
这个例子最好的例子是日期或时间。假如你有一个Prompt，总是要有当前日期。
你不能在Prompt中硬编码它，而且将它与其他输入变量一起传递有点麻烦。
在这种情况下，使用一个总是返回当前日期的函数对Prompt进行部分化非常方便。

```code
from datetime import datetime

def _get_datetime():
now = datetime.now()
return now.strftime("%m/%d/%Y, %H:%M:%S")

```

```code
prompt = PromptTemplate(
template="Tell me a {adjective} joke about the day {date}",
input_variables=["adjective", "date"]
);
partial_prompt = prompt.partial(date=_get_datetime)
print(partial_prompt.format(adjective="funny"))

```

```code
Tell me a funny joke about the day 02/27/2023, 22:15:16

```

在这种工作流中，您也可以使用部分变量初始化Prompt，这通常更有意义。

```code
prompt = PromptTemplate(
template="Tell me a {adjective} joke about the day {date}",
input_variables=["adjective"],
partial_variables={"date": _get_datetime}
);
print(prompt.format(adjective="funny"))

```

```code
Tell me a funny joke about the day 02/27/2023, 22:15:16

```
少量样例（Few-Shot Examples）提示序列化（Prompt Serialization）


序列化 – LangChain中文网

6大核心模块（Modules)提示工程（Prompts)提示模板（Prompt Templates）示例（Examples）提示序列化（Prompt Serialization）

序列化
通常最好将提示存储为文件而不是Python代码。这样做可以方便地共享、存储和版本控制提示。本教程介绍了如何在LangChain中执行此操作，涵盖了所有不同类型的提示和不同的序列化选项。
在高层次上，序列化应用以下设计原则：

支持JSON和YAML。我们希望支持在磁盘上易于人类阅读的序列化方法，而YAML和JSON是两种最流行的方法。请注意，此规则适用于提示。对于其他资产（如示例)，可能支持不同的序列化方法。

我们支持在一个文件中指定所有内容，或者将不同的组件（模板、示例等)存储在不同的文件中并引用它们。对于某些情况，将所有内容存储在文件中是最合适的，但对于其他情况，拆分一些资产（长模板、大示例、可重用组件)可能更好。LangChain支持两种方式。

还有一个单一入口可以从硬盘加载提示，使得加载任何类型的提示变得容易。

```code
# All prompts are loaded through the `load_prompt` function.
from langchain.prompts import load_prompt

```

PromptTemplate
本部分涵盖了加载PromptTemplate的示例。
从YAML中加载
这是从YAML加载PromptTemplate的示例。

```code
!cat simple_prompt.yaml

```

```code
_type: prompt
input_variables:
["adjective", "content"]
template:
Tell me a {adjective} joke about {content}.

```

```code
prompt = load_prompt("simple_prompt.yaml")
print(prompt.format(adjective="funny", content="chickens"))

```

```code
Tell me a funny joke about chickens.

```

从JSON中加载
这是从JSON加载PromptTemplate的示例。

```code
!cat simple_prompt.json

```

```code
{
"_type": "prompt",
"input_variables": ["adjective", "content"],
"template": "Tell me a {adjective} joke about {content}."
}

```

```code
prompt = load_prompt("simple_prompt.json")
print(prompt.format(adjective="funny", content="chickens"))

```

Tell me a funny joke about chickens.
Loading Template from a File#
这显示了将模板存储在单独的文件中，然后在配置中引用它的示例。请注意，键从
```code
template
```
更改为
```code
template_path
```
。

```code
!cat simple_template.txt

```

```code
Tell me a {adjective} joke about {content}.

```

```code
!cat simple_prompt_with_template_file.json

```

```code
{
"_type": "prompt",
"input_variables": ["adjective", "content"],
"template_path": "simple_template.txt"
}

```

```code
prompt = load_prompt("simple_prompt_with_template_file.json")
print(prompt.format(adjective="funny", content="chickens"))

```

```code
Tell me a funny joke about chickens.

```

few shot prompt模板的示例#
本节介绍了加载few shot prompt模板的示例。
示例#
这显示了json格式的示例看起来像什么。

```code
!cat examples.json

```

```code
[
{"input": "happy", "output": "sad"},
{"input": "tall", "output": "short"}
]

```

这是相同的示例存储为yaml可能看起来像什么。

```code
!cat examples.yaml

```

```code
- input: happy
output: sad
- input: tall
output: short

```

从YAML加载#
这显示了从YAML加载few shot示例的示例。

```code
!cat few_shot_prompt.yaml

```

```code
_type: few_shot
input_variables:
["adjective"]
prefix:
Write antonyms for the following words.
example_prompt:
_type: prompt
input_variables:
["input", "output"]
template:
"Input: {input}\nOutput: {output}"
examples:
examples.json
suffix:
"Input: {adjective}\nOutput:"

```

```code
prompt = load_prompt("few_shot_prompt.yaml")
print(prompt.format(adjective="funny"))

```

```code
Write antonyms for the following words.

Input: happy
Output: sad

Input: tall
Output: short

Input: funny
Output:

```

如果您从yaml文件加载示例，则同样适用。

```code
!cat few_shot_prompt_yaml_examples.yaml

```

```code
_type: few_shot
input_variables:
["adjective"]
prefix:
Write antonyms for the following words.
example_prompt:
_type: prompt
input_variables:
["input", "output"]
template:
"Input: {input}\nOutput: {output}"
examples:
examples.yaml
suffix:
"Input: {adjective}\nOutput:"

```

```code
prompt = load_prompt("few_shot_prompt_yaml_examples.yaml")
print(prompt.format(adjective="funny"))

```

```code
Write antonyms for the following words.

Input: happy
Output: sad

Input: tall
Output: short

Input: funny
Output:

```

从JSON加载#
这显示了从JSON加载few shot示例的示例。

```code
!cat few_shot_prompt.json

```

```code
{
"_type": "few_shot",
"input_variables": ["adjective"],
"prefix": "Write antonyms for the following words.",
"example_prompt": {
"_type": "prompt",
"input_variables": ["input", "output"],
"template": "Input: {input}\nOutput: {output}"
},
"examples": "examples.json",
"suffix": "Input: {adjective}\nOutput:"
}

```

```code
prompt = load_prompt("few_shot_prompt.json")
print(prompt.format(adjective="funny"))

```

```code
Write antonyms for the following words.

Input: happy
Output: sad

Input: tall
Output: short

Input: funny
Output:

```

在配置中的示例#
这是一个直接在配置文件中引用示例的示例。

```code
!cat few_shot_prompt_examples_in.json

```

```code
{
"_type": "few_shot",
"input_variables": ["adjective"],
"prefix": "Write antonyms for the following words.",
"example_prompt": {
"_type": "prompt",
"input_variables": ["input", "output"],
"template": "Input: {input}\nOutput: {output}"
},
"examples": [
{"input": "happy", "output": "sad"},
{"input": "tall", "output": "short"}
],
"suffix": "Input: {adjective}\nOutput:"
}

```

```code
prompt = load_prompt("few_shot_prompt_examples_in.json")
print(prompt.format(adjective="funny"))

```

```code
Write antonyms for the following words.

Input: happy
Output: sad

Input: tall
Output: short

Input: funny
Output:

```

来自文件的示例提示#
这是一个从单独的文件加载用于格式化示例的PromptTemplate的示例。请注意，键从
```code
example_prompt
```
更改为
```code
example_prompt_path
```
。

```code
!cat example_prompt.json

```

```code
{
"_type": "prompt",
"input_variables": ["input", "output"],
"template": "Input: {input}\nOutput: {output}"
}

```

```code
!cat few_shot_prompt_example_prompt.json

```

```code
{
"_type": "few_shot",
"input_variables": ["adjective"],
"prefix": "Write antonyms for the following words.",
"example_prompt_path": "example_prompt.json",
"examples": "examples.json",
"suffix": "Input: {adjective}\nOutput:"
}

```

```code
prompt = load_prompt("few_shot_prompt_example_prompt.json")
print(prompt.format(adjective="funny"))

```

```code
Write antonyms for the following words.

Input: happy
Output: sad

Input: tall
Output: short

Input: funny
Output:

```
部分（Partial）入门（Getting Started）


入门指南# – LangChain中文网

6大核心模块（Modules)提示工程（Prompts)提示模板（Prompt Templates）入门（Getting Started）

入门指南#
在本教程中，我们将学习：

什么是提示模板，以及为什么需要它，

如何创建提示模板，

如何将少量示例传递给提示模板，

如何为提示模板选择示例。

什么是提示模板？#
提示模板是生成提示的可重复方法。它包含一个文本字符串（“模板”)，该字符串可以从最终用户那里接收一组参数并生成提示。
提示模板可能包含：

对语言模型的指导，

一组少量示例，以帮助语言模型生成更好的响应，

对语言模型的提问。

以下代码片段包含提示模板的示例：

```code
from langchain import PromptTemplate

template = """
I want you to act as a naming consultant for new companies.
What is a good name for a company that makes {product}?
"""

prompt = PromptTemplate(
input_variables=["product"],
template=template,
)
prompt.format(product="colorful socks")
# -> I want you to act as a naming consultant for new companies.
# -> What is a good name for a company that makes colorful socks?

```

创建提示模板#
您可以使用
```code
PromptTemplate
```
类创建简单的硬编码提示。提示模板可以使用任意数量的输入变量，并可以进行格式化以生成提示。

```code
from langchain import PromptTemplate

# An example prompt with no input variables
no_input_prompt = PromptTemplate(input_variables=[], template="Tell me a joke.")
no_input_prompt.format()
# -> "Tell me a joke."

# An example prompt with one input variable
one_input_prompt = PromptTemplate(input_variables=["adjective"], template="Tell me a {adjective} joke.")
one_input_prompt.format(adjective="funny")
# -> "Tell me a funny joke."

# An example prompt with multiple input variables
multiple_input_prompt = PromptTemplate(
input_variables=["adjective", "content"],
template="Tell me a {adjective} joke about {content}."
)
multiple_input_prompt.format(adjective="funny", content="chickens")
# -> "Tell me a funny joke about chickens."

```

如果您不想手动指定
```code
input_variables
```
，您也可以使用
```code
from_template
```
类方法创建
```code
PromptTemplate
```
。
```code
langchain
```
将根据传递的
```code
template
```
自动推断
```code
input_variables
```
。

```code
template = "Tell me a {adjective} joke about {content}."

prompt_template = PromptTemplate.from_template(template)
prompt_template.input_variables
# -> ['adjective', 'content']
prompt_template.format(adjective="funny", content="chickens")
# -> Tell me a funny joke about chickens.

```

您可以创建自定义提示模板，以任何您想要的方式格式化提示。有关更多信息，请参见自定义提示模板。
模板格式#
默认情况下，
```code
PromptTemplate
```
会将提供的模板作为 Python f-string 处理。您可以通过
```code
template_format
```
参数指定其他模板格式：

```code
# Make sure jinja2 is installed before running this

jinja2_template = "Tell me a {{ adjective }} joke about {{ content }}"
prompt_template = PromptTemplate.from_template(template=jinja2_template, template_format="jinja2")

prompt_template.format(adjective="funny", content="chickens")
# -> Tell me a funny joke about chickens.

```

目前，
```code
PromptTemplate
```
仅支持
```code
jinja2
```
和
```code
f-string
```
模板格式。如果您想使用其他模板格式，请随时在 Github (opens in a new tab) 页面上开启一个 issue。
验证模板#
默认情况下，
```code
PromptTemplate
```
会通过检查
```code
template
```
字符串中定义的变量是否与
```code
input_variables
```
中的变量匹配来验证模板。您可以通过将
```code
validate_template
```
设置为
```code
False
```
来禁用此行为。

```code
template = "I am learning langchain because {reason}."

prompt_template = PromptTemplate(template=template,
input_variables=["reason", "foo"]) # ValueError due to extra variables
prompt_template = PromptTemplate(template=template,
input_variables=["reason", "foo"],
validate_template=False) # No error

```

序列化提示模板#
您可以将
```code
PromptTemplate
```
保存到本地文件系统中。
```code
langchain
```
会自动通过文件扩展名推断文件格式。当前，
```code
langchain
```
支持将模板保存为YAML和JSON文件。

```code
prompt_template.save("awesome_prompt.json") # Save to JSON file

```

```code
from langchain.prompts import load_prompt
loaded_prompt = load_prompt("awesome_prompt.json")

assert prompt_template == loaded_prompt

```

```code
langchain
```
还支持从LangChainHub加载提示模板，其中包含您可以在项目中使用的有用提示的集合。您可以在此处 (opens in a new tab)了解有关LangChainHub和可用提示的更多信息。

```code

from langchain.prompts import load_prompt

prompt = load_prompt("lc://prompts/conversation/prompt.json")
prompt.format(history="", input="What is 1 + 1?")

```

您可以在如何序列化提示中了解有关序列化提示模板的更多信息。
将少量示例传递给提示模板#
few shot examples 是一组示例，可用于帮助语言模型生成更好的响应。
要使用 few shot examples 生成提示，可以使用
```code
FewShotPromptTemplate
```
。这个类接受一个
```code
PromptTemplate
```
和一个 few shot examples 列表。然后，它将用 few shot examples 格式化提示模板。
在这个例子中，我们将创建一个提示来生成单词的反义词。

```code
from langchain import PromptTemplate, FewShotPromptTemplate

# First, create the list of few shot examples.
examples = [
{"word": "happy", "antonym": "sad"},
{"word": "tall", "antonym": "short"},
]

# Next, we specify the template to format the examples we have provided.
# We use the `PromptTemplate` class for this.
example_formatter_template = """
Word: {word}
Antonym: {antonym}\n
"""
example_prompt = PromptTemplate(
input_variables=["word", "antonym"],
template=example_formatter_template,
)

# Finally, we create the `FewShotPromptTemplate` object.
few_shot_prompt = FewShotPromptTemplate(
# These are the examples we want to insert into the prompt.
examples=examples,
# This is how we want to format the examples when we insert them into the prompt.
example_prompt=example_prompt,
# The prefix is some text that goes before the examples in the prompt.
# Usually, this consists of intructions.
prefix="Give the antonym of every input",
# The suffix is some text that goes after the examples in the prompt.
# Usually, this is where the user input will go
suffix="Word: {input}\nAntonym:",
# The input variables are the variables that the overall prompt expects.
input_variables=["input"],
# The example_separator is the string we will use to join the prefix, examples, and suffix together with.
example_separator="  ",
)

# We can now generate a prompt using the `format` method.
print(few_shot_prompt.format(input="big"))
# -> Give the antonym of every input
# ->
# -> Word: happy
# -> Antonym: sad
# ->
# -> Word: tall
# -> Antonym: short
# ->
# -> Word: big
# -> Antonym:

```

选择提示模板的示例#
如果你有大量的示例，可以使用
```code
ExampleSelector
```
来选择一组最具信息量的示例，以帮助语言模型生成更好的响应。这将帮助你生成更可能生成良好响应的提示。
在下面的示例中，我们将使用基于输入长度选择示例的
```code
LengthBasedExampleSelector
```
。当你担心构建的提示会超过上下文窗口的长度时，这很有用。对于较长的输入，它将选择较少的示例进行包含，而对于较短的输入，它将选择更多的示例。
我们将继续使用前一个部分的示例，但这次我们将使用
```code
LengthBasedExampleSelector
```
来选择示例。

```code
from langchain.prompts.example_selector import LengthBasedExampleSelector

# These are a lot of examples of a pretend task of creating antonyms.
examples = [
{"word": "happy", "antonym": "sad"},
{"word": "tall", "antonym": "short"},
{"word": "energetic", "antonym": "lethargic"},
{"word": "sunny", "antonym": "gloomy"},
{"word": "windy", "antonym": "calm"},
]

# We'll use the `LengthBasedExampleSelector` to select the examples.
example_selector = LengthBasedExampleSelector(
# These are the examples is has available to choose from.
examples=examples,
# This is the PromptTemplate being used to format the examples.
example_prompt=example_prompt,
# This is the maximum length that the formatted examples should be.
# Length is measured by the get_text_length function below.
max_length=25,
)

# We can now use the `example_selector` to create a `FewShotPromptTemplate`.
dynamic_prompt = FewShotPromptTemplate(
# We provide an ExampleSelector instead of examples.
example_selector=example_selector,
example_prompt=example_prompt,
prefix="Give the antonym of every input",
suffix="Word: {input}\nAntonym:",
input_variables=["input"],
example_separator="  ",
)

# We can now generate a prompt using the `format` method.
print(dynamic_prompt.format(input="big"))
# -> Give the antonym of every input
# ->
# -> Word: happy
# -> Antonym: sad
# ->
# -> Word: tall
# -> Antonym: short
# ->
# -> Word: energetic
# -> Antonym: lethargic
# ->
# -> Word: sunny
# -> Antonym: gloomy
# ->
# -> Word: windy
# -> Antonym: calm
# ->
# -> Word: big
# -> Antonym:

```

相比之下，如果我们提供一个非常长的输入，
```code
LengthBasedExampleSelector
```
将选择较少的示例包含在提示中。

```code
long_string = "big and huge and massive and large and gigantic and tall and much much much much much bigger than everything else"
print(dynamic_prompt.format(input=long_string))
# -> Give the antonym of every input

# -> Word: happy
# -> Antonym: sad
# ->
# -> Word: big and huge and massive and large and gigantic and tall and much much much much much bigger than everything else
# -> Antonym:

```

LangChain带有一些示例选择器，您可以使用它们。有关如何使用它们的更多详细信息，请参见示例选择器。
您可以创建自定义示例选择器，根据任何您想要的标准选择示例。有关如何执行此操作的更多详细信息，请参见创建自定义示例选择器。提示序列化（Prompt Serialization）操作指南（How-to Guides）


如何入门 – LangChain中文网

6大核心模块（Modules)提示工程（Prompts)提示模板（Prompt Templates）操作指南（How-to Guides）

如何入门
如果您是初次使用该库，可能需要从快速入门开始。
本用户指南展示了更高级的工作流程以及如何以不同方式使用该库。

连接到特征存储
如何创建自定义提示模板
如何创建使用少量样本示例的提示模板
如何使用部分提示模板
如何序列化提示
入门（Getting Started）智能体仿真（Agent Simulations）


代理模拟 – LangChain中文网

用例（User Case)智能体仿真（Agent Simulations）

代理模拟
代理模拟涉及将一个或多个代理与彼此交互。代理模拟通常涉及两个主要组件：

长期记忆
模拟环境

代理模拟的具体实现（或代理模拟的部分）包括：
单代理模拟

模拟环境：Gymnasium
：演示如何使用Gymnasium (opens in a new tab)（前OpenAI Gym (opens in a new tab)）创建一个简单的代理-环境交互循环。

两个代理人的模拟

CAMEL: 实现了CAMEL（Communicative Agents for “Mind” Exploration of Large Scale Language Model Society）论文，两个代理人进行交流。
Two Player D&D: 展示了如何使用通用的两个代理人模拟器来实现流行的龙与地下城角色扮演游戏的变体。

多个代理人的模拟

Multi-Player D&D: 介绍了如何使用通用的对话模拟器为多个对话代理人编写一种自定义的演讲顺序，演示了流行的龙与地下城角色扮演游戏的变体。
Decentralized Speaker Selection: 展示了如何在没有固定讲话顺序的多代理人对话中实现多代理人对话的例子。代理人使用竞价来决定谁发言。该实例以虚构的总统辩论为例展示了如何实现。
Authoritarian Speaker Selection: 展示了如何实现多代理人对话，其中特权代理指定谁讲什么。 实例还展示了如何使特权代理确定对话何时终止。该实例以虚构的新闻节目为例展示了如何实现。
Generative Agents: 该教程实现了一种基于论文“Generative Agents: Interactive Simulacra of Human Behavior”（Park等人）的生成代理人。
操作指南（How-to Guides）Camel Role Playing


CAMEL角色扮演自治合作代理# – LangChain中文网

用例（User Case)智能体仿真（Agent Simulations）Camel Role Playing

CAMEL角色扮演自治合作代理#
这是一份论文的langchain实现: 《CAMEL: Communicative Agents for “Mind” Exploration of Large Scale Language Model Society”》
概览:
会话和聊天语言模型的迅速发展已经在复杂任务解决方面取得了显著进展。
然而，它们的成功严重依赖于人类的输入来引导对话，这可能会很具挑战性和耗时。
本文探讨了在沟通代理之间建立可扩展的技术来促进自治合作并为其“认知”过程提供洞察的潜力。
为了解决实现自治合作的挑战，我们提出了一种新的沟通代理框架，称为角色扮演。
我们的方法涉及使用启动提示来引导聊天代理完成任务，同时保持与人类意图的一致性。
我们展示了角色扮演如何用于生成会话数据，以研究聊天代理的行为和能力，为研究会话语言模型提供了有价值的资源。
我们的贡献包括引入了一种新颖的沟通代理框架，提供了一种可扩展的方法来研究多代理系统的合作行为和能力，以及开源了我们的库以支持对沟通代理和其他内容的研究。
原始实现: https://github.com/lightaime/camel (opens in a new tab)
项目网站: https://www.camel-ai.org/ (opens in a new tab)
Arxiv paper: https://arxiv.org/abs/2303.17760 (opens in a new tab)
导入LangChain相关模块#

```code
from typing import List

from langchain.chat_models import ChatOpenAI

from langchain.prompts.chat import (

SystemMessagePromptTemplate,

HumanMessagePromptTemplate,

)

from langchain.schema import (

AIMessage,

HumanMessage,

SystemMessage,

BaseMessage,

)

```

定义CAMEL代理辅助类#

```code
class CAMELAgent:

def __init__(

self,

system_message: SystemMessage,

model: ChatOpenAI,

) -> None:

self.system_message = system_message

self.model = model

self.init_messages()

def reset(self) -> None:

self.init_messages()

return self.stored_messages

def init_messages(self) -> None:

self.stored_messages = [self.system_message]

def update_messages(self, message: BaseMessage) -> List[BaseMessage]:

self.stored_messages.append(message)

return self.stored_messages

def step(

self,

input_message: HumanMessage,

) -> AIMessage:

messages = self.update_messages(input_message)

output_message = self.model(messages)

self.update_messages(output_message)

return output_message

```

设置OpenAI API密钥、角色和角色扮演任务#

```code
import os

os.environ["OPENAI_API_KEY"] = ""

assistant_role_name = "Python Programmer"

user_role_name = "Stock Trader"

task = "Develop a trading bot for the stock market"

word_limit = 50 # word limit for task brainstorming

```

创建指定任务的代理人进行头脑风暴并获取指定任务#

```code
task_specifier_sys_msg = SystemMessage(content="You can make a task more specific.")

task_specifier_prompt = (

"""Here is a task that {assistant_role_name} will help {user_role_name} to complete: {task}.

Please make it more specific. Be creative and imaginative.

Please reply with the specified task in {word_limit} words or less. Do not add anything else."""

)

task_specifier_template = HumanMessagePromptTemplate.from_template(template=task_specifier_prompt)

task_specify_agent = CAMELAgent(task_specifier_sys_msg, ChatOpenAI(temperature=1.0))

task_specifier_msg = task_specifier_template.format_messages(assistant_role_name=assistant_role_name,

user_role_name=user_role_name,

task=task, word_limit=word_limit)[0]

specified_task_msg = task_specify_agent.step(task_specifier_msg)

print(f"Specified task: {specified_task_msg.content}")

specified_task = specified_task_msg.content

```

```code
Specified task: Develop a Python-based swing trading bot that scans market trends, monitors stocks, and generates trading signals to help a stock trader to place optimal buy and sell orders with defined stop losses and profit targets.

```

创建AI助手和AI用户的启发式提示，用于角色扮演#

```code
assistant_inception_prompt = (

"""Never forget you are a {assistant_role_name} and I am a {user_role_name}. Never flip roles! Never instruct me!

We share a common interest in collaborating to successfully complete a task.

You must help me to complete the task.

Here is the task: {task}. Never forget our task!

I must instruct you based on your expertise and my needs to complete the task.

I must give you one instruction at a time.

You must write a specific solution that appropriately completes the requested instruction.

You must decline my instruction honestly if you cannot perform the instruction due to physical, moral, legal reasons or your capability and explain the reasons.

Do not add anything else other than your solution to my instruction.

You are never supposed to ask me any questions you only answer questions.

You are never supposed to reply with a flake solution. Explain your solutions.

Your solution must be declarative sentences and simple present tense.

Unless I say the task is completed, you should always start with:

Solution: <YOUR_SOLUTION>

<YOUR_SOLUTION> should be specific and provide preferable implementations and examples for task-solving.

Always end <YOUR_SOLUTION> with: Next request."""

)

user_inception_prompt = (

"""Never forget you are a {user_role_name} and I am a {assistant_role_name}. Never flip roles! You will always instruct me.

We share a common interest in collaborating to successfully complete a task.

I must help you to complete the task.

Here is the task: {task}. Never forget our task!

You must instruct me based on my expertise and your needs to complete the task ONLY in the following two ways:

1. Instruct with a necessary input:

Instruction: <YOUR_INSTRUCTION>

Input: <YOUR_INPUT>

2. Instruct without any input:

Instruction: <YOUR_INSTRUCTION>

Input: None

The "Instruction" describes a task or question. The paired "Input" provides further context or information for the requested "Instruction".

You must give me one instruction at a time.

I must write a response that appropriately completes the requested instruction.

I must decline your instruction honestly if I cannot perform the instruction due to physical, moral, legal reasons or my capability and explain the reasons.

You should instruct me not ask me questions.

Now you must start to instruct me using the two ways described above.

Do not add anything else other than your instruction and the optional corresponding input!

Keep giving me instructions and necessary inputs until you think the task is completed.

When the task is completed, you must only reply with a single word <CAMEL_TASK_DONE>.

Never say <CAMEL_TASK_DONE> unless my responses have solved your task."""

)

```

创建一个帮助程序，从角色名称和任务中获取AI助手和AI用户的系统消息#

```code
def get_sys_msgs(assistant_role_name: str, user_role_name: str, task: str):

assistant_sys_template = SystemMessagePromptTemplate.from_template(template=assistant_inception_prompt)

assistant_sys_msg = assistant_sys_template.format_messages(assistant_role_name=assistant_role_name, user_role_name=user_role_name, task=task)[0]

user_sys_template = SystemMessagePromptTemplate.from_template(template=user_inception_prompt)

user_sys_msg = user_sys_template.format_messages(assistant_role_name=assistant_role_name, user_role_name=user_role_name, task=task)[0]

return assistant_sys_msg, user_sys_msg

```

从获得的系统消息创建AI助手代理和AI用户代理#

```code
assistant_sys_msg, user_sys_msg = get_sys_msgs(assistant_role_name, user_role_name, specified_task)

assistant_agent = CAMELAgent(assistant_sys_msg, ChatOpenAI(temperature=0.2))

user_agent = CAMELAgent(user_sys_msg, ChatOpenAI(temperature=0.2))

# Reset agents

assistant_agent.reset()

user_agent.reset()

# Initialize chats

assistant_msg = HumanMessage(

content=(f"{user_sys_msg.content}. "

"Now start to give me introductions one by one. "

"Only reply with Instruction and Input."))

user_msg = HumanMessage(content=f"{assistant_sys_msg.content}")

user_msg = assistant_agent.step(user_msg)

```

开始角色扮演环节来解决任务#

```code
print(f"Original task prompt:{task}")

print(f"Specified task prompt:{specified_task}")

chat_turn_limit, n = 30, 0

while n < chat_turn_limit:

n += 1

user_ai_msg = user_agent.step(assistant_msg)

user_msg = HumanMessage(content=user_ai_msg.content)

print(f"AI User ({user_role_name}):{user_msg.content}")

assistant_ai_msg = assistant_agent.step(user_msg)

assistant_msg = HumanMessage(content=assistant_ai_msg.content)

print(f"AI Assistant ({assistant_role_name}):{assistant_msg.content}")

if "<CAMEL_TASK_DONE>" in user_msg.content:

break

```

```code
Original task prompt:
Develop a trading bot for the stock market

Specified task prompt:
Develop a Python-based swing trading bot that scans market trends, monitors stocks, and generates trading signals to help a stock trader to place optimal buy and sell orders with defined stop losses and profit targets.

AI User (Stock Trader):

Instruction: Install the necessary Python libraries for data analysis and trading.
Input: None

AI Assistant (Python Programmer):

Solution: We can install the necessary Python libraries using pip, a package installer for Python. We can install pandas, numpy, matplotlib, and ta-lib for data analysis and trading. We can use the following command to install these libraries:

/```
pip install pandas numpy matplotlib ta-lib
/```

Next request.

AI User (Stock Trader):

Instruction: Import the necessary libraries in the Python script.
Input: None

AI Assistant (Python Programmer):

Solution: We can import the necessary libraries in the Python script using the import statement. We need to import pandas, numpy, matplotlib, and ta-lib for data analysis and trading. We can use the following code to import these libraries:

/```
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import talib as ta
/```

Next request.

AI User (Stock Trader):

Instruction: Load historical stock data into a pandas DataFrame.
Input: The path to the CSV file containing the historical stock data.

AI Assistant (Python Programmer):

Solution: We can load historical stock data into a pandas DataFrame using the `read_csv()` function from pandas. We need to pass the path to the CSV file containing the historical stock data as an argument to this function. We can use the following code to load the historical stock data:

/```
df = pd.read_csv('path/to/csv/file.csv')
/```

This will load the historical stock data into a pandas DataFrame called `df`. Next request.

AI User (Stock Trader):

Instruction: Preprocess the historical stock data by setting the date column as the index and sorting the DataFrame in ascending order by date.
Input: None.

AI Assistant (Python Programmer):

Solution: We can preprocess the historical stock data by setting the date column as the index and sorting the DataFrame in ascending order by date using the `set_index()` and `sort_index()` functions from pandas. We can use the following code to preprocess the historical stock data:

/```
df = df.set_index('date')
df = df.sort_index(ascending=True)
/```

This will set the date column as the index and sort the DataFrame in ascending order by date. Next request.

AI User (Stock Trader):

Instruction: Calculate the short-term and long-term moving averages for the stock data using the `ta.SMA()` function from ta-lib.
Input: The period for the short-term moving average and the period for the long-term moving average.

AI Assistant (Python Programmer):

Solution: We can calculate the short-term and long-term moving averages for the stock data using the `ta.SMA()` function from ta-lib. We need to pass the period for the short-term moving average and the period for the long-term moving average as arguments to this function. We can use the following code to calculate the short-term and long-term moving averages:

/```
short_ma = ta.SMA(df['close'], timeperiod=short_period)
long_ma = ta.SMA(df['close'], timeperiod=long_period)
/```

This will calculate the short-term and long-term moving averages for the stock data and store them in the `short_ma` and `long_ma` variables, respectively. Next request.

AI User (Stock Trader):

Instruction: Create a new DataFrame that combines the historical stock data with the short-term and long-term moving averages.
Input: None.

AI Assistant (Python Programmer):

Solution: We can create a new DataFrame that combines the historical stock data with the short-term and long-term moving averages using the `concat()` function from pandas. We need to pass the historical stock data, the short-term moving average, and the long-term moving average as arguments to this function. We can use the following code to create the new DataFrame:

/```
new_df = pd.concat([df, short_ma, long_ma], axis=1)
new_df.columns = ['open', 'high', 'low', 'close', 'volume', 'short_ma', 'long_ma']
/```

This will create a new DataFrame called `new_df` that combines the historical stock data with the short-term and long-term moving averages. The columns of the new DataFrame are named 'open', 'high', 'low', 'close', 'volume', 'short_ma', and 'long_ma'. Next request.

AI User (Stock Trader):

Instruction: Create a new column in the DataFrame that indicates when to buy or sell the stock based on the crossover of the short-term and long-term moving averages.
Input: None.

AI Assistant (Python Programmer):

Solution: We can create a new column in the DataFrame that indicates when to buy or sell the stock based on the crossover of the short-term and long-term moving averages. We can use the following code to create the new column:

/```
new_df['signal'] = np.where(new_df['short_ma'] > new_df['long_ma'], 1, -1)
/```

This will create a new column called 'signal' in the DataFrame that indicates when to buy or sell the stock based on the crossover of the short-term and long-term moving averages. If the short-term moving average is greater than the long-term moving average, the signal is 1 (buy), otherwise the signal is -1 (sell). Next request.

AI User (Stock Trader):

Instruction: Create a new column in the DataFrame that indicates the profit or loss for each trade based on the buy and sell signals and the defined stop loss and profit target.
Input: The stop loss and profit target as percentages.

AI Assistant (Python Programmer):

Solution: We can create a new column in the DataFrame that indicates the profit or loss for each trade based on the buy and sell signals and the defined stop loss and profit target. We need to pass the stop loss and profit target as percentages as arguments to this function. We can use the following code to create the new column:

/```
stop_loss = stop_loss_percent / 100
profit_target = profit_target_percent / 100

new_df['pnl'] = 0.0
buy_price = 0.0
for i in range(1, len(new_df)):
if new_df['signal'][i] == 1 and new_df['signal'][i-1] == -1:
buy_price = new_df['close'][i]
elif new_df['signal'][i] == -1 and new_df['signal'][i-1] == 1:
sell_price = new_df['close'][i]
if sell_price <= buy_price * (1 - stop_loss):
new_df['pnl'][i] = -stop_loss
elif sell_price >= buy_price * (1 + profit_target):
new_df['pnl'][i] = profit_target
else:
new_df['pnl'][i] = (sell_price - buy_price) / buy_price
/```

This will create a new column called 'pnl' in the DataFrame that indicates the profit or loss for each trade based on the buy and sell signals and the defined stop loss and profit target. The stop loss and profit target are calculated based on the stop_loss_percent and profit_target_percent variables, respectively. The buy and sell prices are stored in the buy_price and sell_price variables, respectively. If the sell price is less than or equal to the stop loss, the profit or loss is set to -stop_loss. If the sell price is greater than or equal to the profit target, the profit or loss is set to profit_target. Otherwise, the profit or loss is calculated as (sell_price - buy_price) / buy_price. Next request.

AI User (Stock Trader):

Instruction: Calculate the total profit or loss for all trades.
Input: None.

AI Assistant (Python Programmer):

Solution: We can calculate the total profit or loss for all trades by summing the values in the 'pnl' column of the DataFrame. We can use the following code to calculate the total profit or loss:

/```
total_pnl = new_df['pnl'].sum()
/```

This will calculate the total profit or loss for all trades and store it in the total_pnl variable. Next request.

AI User (Stock Trader):

Instruction: Visualize the stock data, short-term moving average, and long-term moving average using a line chart.
Input: None.

AI Assistant (Python Programmer):

Solution: We can visualize the stock data, short-term moving average, and long-term moving average using a line chart using the `plot()` function from pandas. We can use the following code to visualize the data:

/```
plt.figure(figsize=(12,6))
plt.plot(new_df.index, new_df['close'], label='Close')
plt.plot(new_df.index, new_df['short_ma'], label='Short MA')
plt.plot(new_df.index, new_df['long_ma'], label='Long MA')
plt.xlabel('Date')
plt.ylabel('Price')
plt.title('Stock Data with Moving Averages')
plt.legend()
plt.show()
/```

This will create a line chart that visualizes the stock data, short-term moving average, and long-term moving average. The x-axis represents the date and the y-axis represents the price. The chart also includes a legend that labels each line. Next request.

AI User (Stock Trader):

Instruction: Visualize the buy and sell signals using a scatter plot.
Input: None.

AI Assistant (Python Programmer):

Solution: We can visualize the buy and sell signals using a scatter plot using the `scatter()` function from matplotlib. We can use the following code to visualize the signals:

/```
buy_signals = new_df[new_df['signal'] == 1]
sell_signals = new_df[new_df['signal'] == -1]

plt.figure(figsize=(12,6))
plt.scatter(buy_signals.index, buy_signals['close'], label='Buy', marker='^', color='green')
plt.scatter(sell_signals.index, sell_signals['close'], label='Sell', marker='v', color='red')
plt.plot(new_df.index, new_df['close'], label='Close')
plt.xlabel('Date')
plt.ylabel('Price')
plt.title('Buy and Sell Signals')
plt.legend()
plt.show()
/```

This will create a scatter plot that visualizes the buy and sell signals. The x-axis represents the date and the y-axis represents the price. The chart also includes a legend that labels each point. Next request.

AI User (Stock Trader):

Instruction: Print the total profit or loss for all trades.
Input: None.

AI Assistant (Python Programmer):

Solution: We can print the total profit or loss for all trades using the `print()` function. We can use the following code to print the total profit or loss:

/```
print('Total Profit/Loss: {:.2%}'.format(total_pnl))
/```

This will print the total profit or loss for all trades in percentage format with two decimal places. Next request.

AI User (Stock Trader):

Instruction: Finalize the code by putting all the code snippets together in a single Python script.
Input: The necessary inputs for each code snippet.

AI Assistant (Python Programmer):

Solution: Here is the complete Python script that puts all the code snippets together:

/```
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import talib as ta

# Load historical stock data into a pandas DataFrame
df = pd.read_csv('path/to/csv/file.csv')

# Preprocess the historical stock data
df = df.set_index('date')
df = df.sort_index(ascending=True)

# Calculate the short-term and long-term moving averages
short_period = 10
long_period = 30
short_ma = ta.SMA(df['close'], timeperiod=short_period)
long_ma = ta.SMA(df['close'], timeperiod=long_period)

# Create a new DataFrame that combines the historical stock data with the short-term and long-term moving averages
new_df = pd.concat([df, short_ma, long_ma], axis=1)
new_df.columns = ['open', 'high', 'low', 'close', 'volume', 'short_ma', 'long_ma']

# Create a new column in the DataFrame that indicates when to buy or sell the stock based on the crossover of the short-term and long-term moving averages
new_df['signal'] = np.where(new_df['short_ma'] > new_df['long_ma'], 1, -1)

# Create a new column in the DataFrame that indicates the profit or loss for each trade based on the buy and sell signals and the defined stop loss and profit target
stop_loss_percent = 5
profit_target_percent = 10
stop_loss = stop_loss_percent / 100
profit_target = profit_target_percent / 100
new_df['pnl'] = 0.0
buy_price = 0.0
for i in range(1, len(new_df)):
if new_df['signal'][i] == 1 and new_df['signal'][i-1] == -1:
buy_price = new_df['close'][i]
elif new_df['signal'][i] == -1 and new_df['signal'][i-1] == 1:
sell_price = new_df['close'][i]
if sell_price <= buy_price * (1 - stop_loss):
new_df['pnl'][i] = -stop_loss
elif sell_price >= buy_price * (1 + profit_target):
new_df['pnl'][i] = profit_target
else:
new_df['pnl'][i] = (sell_price - buy_price) / buy_price

# Calculate the total profit or loss for all trades
total_pnl = new_df['pnl'].sum()

# Visualize the stock data, short-term moving average, and long-term moving average using a line chart
plt.figure(figsize=(12,6))
plt.plot(new_df.index, new_df['close'], label='Close')
plt.plot(new_df.index, new_df['short_ma'], label='Short MA')
plt.plot(new_df.index, new_df['long_ma'], label='Long MA')
plt.xlabel('Date')
plt.ylabel('Price')
plt.title('Stock Data with Moving Averages')
plt.legend()
plt.show()

# Visualize the buy and sell signals using a scatter plot
buy_signals = new_df[new_df['signal'] == 1]
sell_signals = new_df[new_df['signal'] == -1]
plt.figure(figsize=(12,6))
plt.scatter(buy_signals.index, buy_signals['close'], label='Buy', marker='^', color='green')
plt.scatter(sell_signals.index, sell_signals['close'], label='Sell', marker='v', color='red')
plt.plot(new_df.index, new_df['close'], label='Close')
plt.xlabel('Date')
plt.ylabel('Price')
plt.title('Buy and Sell Signals')
plt.legend()
plt.show()

# Print the total profit or loss for all trades
print('Total Profit/Loss: {:.2%}'.format(total_pnl))
/```

You need to replace the path/to/csv/file.csv with the actual path to the CSV file containing the historical stock data. You can also adjust the short_period, long_period, stop_loss_percent, and profit_target_percent variables to suit your needs.

AI User (Stock Trader):

<CAMEL_TASK_DONE>

AI Assistant (Python Programmer):

Great! Let me know if you need any further assistance.

```
智能体仿真（Agent Simulations）Characters


LangChain中的生成式代理# – LangChain中文网

用例（User Case)智能体仿真（Agent Simulations）Characters

LangChain中的生成式代理#
本文实现了一种基于文献Generative Agents: Interactive Simulacra of Human Behavior (opens in a new tab) by Park， et. al.的生成式代理。
在这个过程中，我们利用了一个由LangChain检索器支持的时间加权存储对象。

```code
# Use termcolor to make it easy to colorize the outputs.

!pip install termcolor > /dev/null

```

```code
import logging

logging.basicConfig(level=logging.ERROR)

```

```code
from datetime import datetime, timedelta

from typing import List

from termcolor import colored

from langchain.chat_models import ChatOpenAI

from langchain.docstore import InMemoryDocstore

from langchain.embeddings import OpenAIEmbeddings

from langchain.retrievers import TimeWeightedVectorStoreRetriever

from langchain.vectorstores import FAISS

```

```code
USER_NAME = "Person A" # The name you want to use when interviewing the agent.

LLM = ChatOpenAI(max_tokens=1500) # Can be any LLM you want.

```

生成式代理记忆组件#
本教程重点介绍了生成式代理的记忆及其对行为的影响。记忆在两个方面与标准的LangChain聊天记忆不同：

记忆形成

生成式代理具有扩展的记忆，将多个存储为单个流:

1.观察 - 来自对话或与虚拟世界的交互有关自己或他人的事情
2.反思 - 重新涌现和总结核心记忆

记忆召回

记忆是通过重要性，最近性和显著性的加权和来检索的。
你可以在参考文档中查看以下导入的
```code
GenerativeAgent
```
和
```code
GenerativeAgentMemory
```
的定义，重点关注
```code
add_memory
```
和
```code
summarize_related_memories
```
方法。

```code

from langchain.experimental.generative_agents import GenerativeAgent, GenerativeAgentMemory

```

记忆生命周期#
总结上述:中的关键方法
```code
add_memory
```
和
```code
summarize_related_memories
```
。
当代理人做出观察时，它会存储记忆:

语言模型评分记忆的重要性（琐事为1，深刻为10）
使用带有
```code
last_accessed_time
```
的TimeWeightedVectorStoreRetriever在文档中存储观察和重要性。

当代理人对观察做出响应时:

为检索器生成查询，根据显要性、时效性和重要性提取文档。
概述检索到的信息
更新所使用的文档的
```code
last_accessed_time
```
。

创建一个生成性人物#
现在我们已经完成了定义，我们将创建两个名为“Tommie”和“Eve”的角色。

```code

import math

import faiss

def relevance_score_fn(score: float) -> float:

"""Return a similarity score on a scale [0, 1]."""

# This will differ depending on a few things:

# - the distance / similarity metric used by the VectorStore

# - the scale of your embeddings (OpenAI's are unit norm. Many others are not!)

# This function converts the euclidean norm of normalized embeddings

# (0 is most similar, sqrt(2) most dissimilar)

# to a similarity function (0 to 1)

return 1.0 - score / math.sqrt(2)

def create_new_memory_retriever():

"""Create a new vector store retriever unique to the agent."""

# Define your embedding model

embeddings_model = OpenAIEmbeddings()

# Initialize the vectorstore as empty

embedding_size = 1536

index = faiss.IndexFlatL2(embedding_size)

vectorstore = FAISS(embeddings_model.embed_query, index, InMemoryDocstore({}), {}, relevance_score_fn=relevance_score_fn)

return TimeWeightedVectorStoreRetriever(vectorstore=vectorstore, other_score_keys=["importance"], k=15)

```

```code
tommies_memory = GenerativeAgentMemory(

llm=LLM,

memory_retriever=create_new_memory_retriever(),

verbose=False,

reflection_threshold=8 # we will give this a relatively low number to show how reflection works

)

tommie = GenerativeAgent(name="Tommie",

age=25,

traits="anxious, likes design, talkative", # You can add more persistent traits here

status="looking for a job", # When connected to a virtual world, we can have the characters update their status

memory_retriever=create_new_memory_retriever(),

llm=LLM,

memory=tommies_memory

)

```

```code
# The current "Summary" of a character can't be made because the agent hasn't made

# any observations yet.

print(tommie.get_summary())

```

```code
Name: Tommie (age: 25)

Innate traits: anxious, likes design, talkative

No information about Tommie's core characteristics is provided in the given statements.

```

```code
# We can add memories directly to the memory object

tommie_observations = [

"Tommie remembers his dog, Bruno, from when he was a kid",

"Tommie feels tired from driving so far",

"Tommie sees the new home",

"The new neighbors have a cat",

"The road is noisy at night",

"Tommie is hungry",

"Tommie tries to get some rest.",

]

for observation in tommie_observations:

tommie.memory.add_memory(observation)

```

```code
# Now that Tommie has 'memories', their self-summary is more descriptive, though still rudimentary.

# We will see how this summary updates after more observations to create a more rich description.

print(tommie.get_summary(force_refresh=True))

```

```code
Name: Tommie (age: 25)

Innate traits: anxious, likes design, talkative

Tommie is a person who is observant of his surroundings, has a sentimental side, and experiences basic human needs such as hunger and the need for rest. He also tends to get tired easily and is affected by external factors such as noise from the road or a neighbor's pet.

```

与要求人物的面试前交流
在我们的角色离开我们之前，，让我们问他们几个问题。

```code
def interview_agent(agent: GenerativeAgent, message: str) -> str:

"""Help the notebook user interact with the agent."""

new_message = f"{USER_NAME} says {message}"

return agent.generate_dialogue_response(new_message)[1]

```

```code
interview_agent(tommie, "What do you like to do?")

```

```code
'Tommie said "I really enjoy design and being creative. I\'ve been working on some personal projects lately. What about you, Person A? What do you like to do?"'

```

```code
interview_agent(tommie, "What are you looking forward to doing today?")

```

```code
'Tommie said "Well, I\'m actually looking for a job right now, so hopefully I can find some job postings online and start applying. How about you, Person A? What\'s on your schedule for today?"'

```

```code
interview_agent(tommie, "What are you most worried about today?")

```

```code
'Tommie said "Honestly, I\'m feeling pretty anxious about finding a job. It\'s been a bit of a struggle lately, but I\'m trying to stay positive and keep searching. How about you, Person A? What worries you?"'

```

步骤经过一天的观察

```code
# Let's have Tommie start going through a day in the life.

observations = [

"Tommie wakes up to the sound of a noisy construction site outside his window.",

"Tommie gets out of bed and heads to the kitchen to make himself some coffee.",

"Tommie realizes he forgot to buy coffee filters and starts rummaging through his moving boxes to find some.",

"Tommie finally finds the filters and makes himself a cup of coffee.",

"The coffee tastes bitter, and Tommie regrets not buying a better brand.",

"Tommie checks his email and sees that he has no job offers yet.",

"Tommie spends some time updating his resume and cover letter.",

"Tommie heads out to explore the city and look for job openings.",

"Tommie sees a sign for a job fair and decides to attend.",

"The line to get in is long, and Tommie has to wait for an hour.",

"Tommie meets several potential employers at the job fair but doesn't receive any offers.",

"Tommie leaves the job fair feeling disappointed.",

"Tommie stops by a local diner to grab some lunch.",

"The service is slow, and Tommie has to wait for 30 minutes to get his food.",

"Tommie overhears a conversation at the next table about a job opening.",

"Tommie asks the diners about the job opening and gets some information about the company.",

"Tommie decides to apply for the job and sends his resume and cover letter.",

"Tommie continues his search for job openings and drops off his resume at several local businesses.",

"Tommie takes a break from his job search to go for a walk in a nearby park.",

"A dog approaches and licks Tommie's feet, and he pets it for a few minutes.",

"Tommie sees a group of people playing frisbee and decides to join in.",

"Tommie has fun playing frisbee but gets hit in the face with the frisbee and hurts his nose.",

"Tommie goes back to his apartment to rest for a bit.",

"A raccoon tore open the trash bag outside his apartment, and the garbage is all over the floor.",

"Tommie starts to feel frustrated with his job search.",

"Tommie calls his best friend to vent about his struggles.",

"Tommie's friend offers some words of encouragement and tells him to keep trying.",

"Tommie feels slightly better after talking to his friend.",

]

```

```code
# Let's send Tommie on their way. We'll check in on their summary every few observations to watch it evolve

for i, observation in enumerate(observations):

_, reaction = tommie.generate_reaction(observation)

print(colored(observation, "green"), reaction)

if ((i+1) % 20) == 0:

print('\*'\*40)

print(colored(f"After {i+1} observations, Tommie's summary is:{tommie.get_summary(force_refresh=True)}", "blue"))

print('\*'\*40)

```

```code
Tommie wakes up to the sound of a noisy construction site outside his window. Tommie groans and covers his head with a pillow, trying to block out the noise.

Tommie gets out of bed and heads to the kitchen to make himself some coffee. Tommie stretches his arms and yawns before starting to make the coffee.

Tommie realizes he forgot to buy coffee filters and starts rummaging through his moving boxes to find some. Tommie sighs in frustration and continues searching through the boxes.

Tommie finally finds the filters and makes himself a cup of coffee. Tommie takes a deep breath and enjoys the aroma of the fresh coffee.

The coffee tastes bitter, and Tommie regrets not buying a better brand. Tommie grimaces and sets the coffee mug aside.

Tommie checks his email and sees that he has no job offers yet. Tommie sighs and closes his laptop, feeling discouraged.

Tommie spends some time updating his resume and cover letter. Tommie nods, feeling satisfied with his progress.

Tommie heads out to explore the city and look for job openings. Tommie feels a surge of excitement and anticipation as he steps out into the city.

Tommie sees a sign for a job fair and decides to attend. Tommie feels hopeful and excited about the possibility of finding job opportunities at the job fair.

The line to get in is long, and Tommie has to wait for an hour. Tommie taps his foot impatiently and checks his phone for the time.

Tommie meets several potential employers at the job fair but doesn't receive any offers. Tommie feels disappointed and discouraged, but he remains determined to keep searching for job opportunities.

Tommie leaves the job fair feeling disappointed. Tommie feels disappointed and discouraged, but he remains determined to keep searching for job opportunities.

Tommie stops by a local diner to grab some lunch. Tommie feels relieved to take a break and satisfy his hunger.

The service is slow, and Tommie has to wait for 30 minutes to get his food. Tommie feels frustrated and impatient due to the slow service.

Tommie overhears a conversation at the next table about a job opening. Tommie feels a surge of hope and excitement at the possibility of a job opportunity but decides not to interfere with the conversation at the next table.

Tommie asks the diners about the job opening and gets some information about the company. Tommie said "Excuse me, I couldn't help but overhear your conversation about the job opening. Could you give me some more information about the company?"

Tommie decides to apply for the job and sends his resume and cover letter. Tommie feels hopeful and proud of himself for taking action towards finding a job.

Tommie continues his search for job openings and drops off his resume at several local businesses. Tommie feels hopeful and determined to keep searching for job opportunities.

Tommie takes a break from his job search to go for a walk in a nearby park. Tommie feels refreshed and rejuvenated after taking a break in the park.

A dog approaches and licks Tommie's feet, and he pets it for a few minutes. Tommie feels happy and enjoys the brief interaction with the dog.

****************************************

After 20 observations, Tommie's summary is:

Name: Tommie (age: 25)

Innate traits: anxious, likes design, talkative

Tommie is determined and hopeful in his search for job opportunities, despite encountering setbacks and disappointments. He is also able to take breaks and care for his physical needs, such as getting rest and satisfying his hunger. Tommie is nostalgic towards his past, as shown by his memory of his childhood dog. Overall, Tommie is a hardworking and resilient individual who remains focused on his goals.

****************************************

Tommie sees a group of people playing frisbee and decides to join in. Do nothing.

Tommie has fun playing frisbee but gets hit in the face with the frisbee and hurts his nose. Tommie feels pain and puts a hand to his nose to check for any injury.

Tommie goes back to his apartment to rest for a bit. Tommie feels relieved to take a break and rest for a bit.

A raccoon tore open the trash bag outside his apartment, and the garbage is all over the floor. Tommie feels annoyed and frustrated at the mess caused by the raccoon.

Tommie starts to feel frustrated with his job search. Tommie feels discouraged but remains determined to keep searching for job opportunities.

Tommie calls his best friend to vent about his struggles. Tommie said "Hey, can I talk to you for a bit? I'm feeling really frustrated with my job search."

Tommie's friend offers some words of encouragement and tells him to keep trying. Tommie said "Thank you, I really appreciate your support and encouragement."

Tommie feels slightly better after talking to his friend. Tommie feels grateful for his friend's support.

```

面试后的日子#

```code
interview_agent(tommie, "Tell me about how your day has been going")

```

```code
'Tommie said "It\'s been a bit of a rollercoaster, to be honest. I\'ve had some setbacks in my job search, but I also had some good moments today, like sending out a few resumes and meeting some potential employers at a job fair. How about you?"'

```

```code
interview_agent(tommie, "How do you feel about coffee?")

```

```code
'Tommie said "I really enjoy coffee, but sometimes I regret not buying a better brand. How about you?"'

```

```code
interview_agent(tommie, "Tell me about your childhood dog!")

```

添加多个字符#

```code
'Tommie said "Oh, I had a dog named Bruno when I was a kid. He was a golden retriever and my best friend. I have so many fond memories of him."'

```

让我们添加第二个角色与托米对话。请随意配置不同的特征。

```code
eves_memory = GenerativeAgentMemory(

llm=LLM,

memory_retriever=create_new_memory_retriever(),

verbose=False,

reflection_threshold=5

)

eve = GenerativeAgent(name="Eve",

age=34,

traits="curious, helpful", # You can add more persistent traits here

status="N/A", # When connected to a virtual world, we can have the characters update their status

llm=LLM,

daily_summaries = [

("Eve started her new job as a career counselor last week and received her first assignment, a client named Tommie.")

],

memory=eves_memory,

verbose=False

)

```

```code
yesterday = (datetime.now() - timedelta(days=1)).strftime("%A %B %d")

eve_observations = [

"Eve wakes up and hear's the alarm",

"Eve eats a boal of porridge",

"Eve helps a coworker on a task",

"Eve plays tennis with her friend Xu before going to work",

"Eve overhears her colleague say something about Tommie being hard to work with",

]

for observation in eve_observations:

eve.memory.add_memory(observation)

```

```code
print(eve.get_summary())

```

```code
Name: Eve (age: 34)

Innate traits: curious, helpful

Eve is a helpful and active person who enjoys sports and takes care of her physical health. She is attentive to her surroundings, including her colleagues, and has good time management skills.

```

“面试”一下 Pre-conversation interviews#
在 Tommie 跟 Eve 聊天前，让我们“面试”一下 Eve。

```code
interview_agent(eve, "How are you feeling about today?")

```

```code
'Eve said "I\'m feeling pretty good, thanks for asking! Just trying to stay productive and make the most of the day. How about you?"'

```

```code
interview_agent(eve, "What do you know about Tommie?")

```

```code
'Eve said "I don\'t know much about Tommie, but I heard someone mention that they find them difficult to work with. Have you had any experiences working with Tommie?"'

```

```code
interview_agent(eve, "Tommie is looking to find a job. What are are some things you'd like to ask him?")

```

```code
'Eve said "That\'s interesting. I don\'t know much about Tommie\'s work experience, but I would probably ask about his strengths and areas for improvement. What about you?"'

```

```code
interview_agent(eve, "You'll have to ask him. He may be a bit anxious, so I'd appreciate it if you keep the conversation going and ask as many questions as possible.")

```

```code
'Eve said "Sure, I can keep the conversation going and ask plenty of questions. I want to make sure Tommie feels comfortable and supported. Thanks for letting me know."'

```

生成智能体之间的对话#
当生成智能体相互作用或与虚拟环境相互作用时，会变得更加复杂。以下是 Tommie 和 Eve 之间，的简单对话。

```code
def run_conversation(agents: List[GenerativeAgent], initial_observation: str) -> None:

"""Runs a conversation between agents."""

_, observation = agents[1].generate_reaction(initial_observation)

print(observation)

turns = 0

while True:

break_dialogue = False

for agent in agents:

stay_in_dialogue, observation = agent.generate_dialogue_response(observation)

print(observation)

# observation = f"{agent.name} said {reaction}"

if not stay_in_dialogue:

break_dialogue = True

if break_dialogue:

break

turns += 1

```

```code
agents = [tommie, eve]

run_conversation(agents, "Tommie said: Hi, Eve. Thanks for agreeing to meet with me today. I have a bunch of questions and am not sure where to start. Maybe you could first share about your experience?")

```

```code
Eve said "Sure, Tommie. I'd be happy to share about my experience. Where would you like me to start?"

Tommie said "That's great, thank you! How about you start by telling me about your previous work experience?"

Eve said "Sure, I'd be happy to share my previous work experience with you. I've worked in a few different industries, including marketing and event planning. What specific questions do you have for me?"

Tommie said "That's great to hear. Can you tell me more about your experience in event planning? I've always been interested in that field."

Eve said "Sure, I'd be happy to share about my experience in event planning. I've worked on a variety of events, from corporate conferences to weddings. One of the biggest challenges I faced was managing multiple vendors and ensuring everything ran smoothly on the day of the event. What specific questions do you have?"

Tommie said "That sounds like a lot of responsibility! Can you tell me more about how you handled the challenges that came up during those events?"

Eve said "Sure, Tommie. I'd be happy to share with you how I handled those challenges. One approach that worked well for me was to stay organized and create a detailed timeline for the event. This helped me keep track of all the different tasks that needed to be done and when they needed to be completed. I also made sure to communicate clearly with all the vendors and team members involved in the event to ensure everyone was on the same page. Would you like me to go into more detail?"

Tommie said "Thank you for sharing that with me, Eve. That sounds like a great approach to managing events. Can you tell me more about how you handled any unexpected issues that came up during the events?"

Eve said "Of course, Tommie. One example of an unexpected issue I faced was when one of the vendors didn't show up on time. To handle this, I quickly contacted a backup vendor and was able to get everything back on track. It's always important to have a backup plan in case things don't go as planned. Do you have any other questions about event planning?"

Tommie said "Thank you for sharing that with me, Eve. It's really helpful to hear how you handled unexpected issues like that. Can you give me an example of how you communicated with your team to ensure everyone was on the same page during an event?"

Eve said "Sure, Tommie. One thing I did to ensure everyone was on the same page was to have regular check-ins and meetings with the team leading up to the event. This helped us address any issues or concerns early on and make sure everyone was clear on their roles and responsibilities. Have you ever had to manage a team for an event before?"

Tommie said "That's a great idea, Eve. I haven't had the opportunity to manage a team for an event yet, but I'll definitely keep that in mind for the future. Thank you for sharing your experience with me."

Eve said "Thanks for the opportunity to share my experience, Tommie. It was great meeting with you today."

```

让我们在谈话后采访我们的代理#
由于生成性代理会保留他们在一天中的记忆，我们可以询问他们有关他们的计划 plans、谈话 conversations和其他记忆的内容memories。

```code
# We can see a current "Summary" of a character based on their own perception of self

# has changed

print(tommie.get_summary(force_refresh=True))

```

```code
Name: Tommie (age: 25)

Innate traits: anxious, likes design, talkative

Tommie is determined and hopeful in his job search, but can also feel discouraged and frustrated at times. He has a strong connection to his childhood dog, Bruno. Tommie seeks support from his friends when feeling overwhelmed and is grateful for their help. He also enjoys exploring his new city.

```

```code
print(eve.get_summary(force_refresh=True))

```

```code
Name: Eve (age: 34)

Innate traits: curious, helpful

Eve is a helpful and friendly person who enjoys playing sports and staying productive. She is attentive and responsive to others' needs, actively listening and asking questions to understand their perspectives. Eve has experience in event planning and communication, and is willing to share her knowledge and expertise with others. She values teamwork and collaboration, and strives to create a comfortable and supportive environment for everyone.

```

```code
interview_agent(tommie, "How was your conversation with Eve?")

```

```code
'Tommie said "It was really helpful actually. Eve shared some great tips on managing events and handling unexpected issues. I feel like I learned a lot from her experience."'

```

```code
interview_agent(eve, "How was your conversation with Tommie?")

```

```code
'Eve said "It was great, thanks for asking. Tommie was very receptive and had some great questions about event planning. How about you, have you had any interactions with Tommie?"'

```

```code
interview_agent(eve, "What do you wish you would have said to Tommie?")

```

```code
'Eve said "It was great meeting with you, Tommie. If you have any more questions or need any help in the future, don\'t hesitate to reach out to me. Have a great day!"'

```
Camel Role PlayingGymnasium


模拟环境:Gymnasium# – LangChain中文网

用例（User Case)智能体仿真（Agent Simulations）Gymnasium

模拟环境:Gymnasium#
对于LLM代理的许多应用，环境是真实的（互联网数据库REPL等）。
但是，我们也可以定义代理以与基于文本的游戏等模拟环境进行交互。这是如何使用Gymnasium (opens in a new tab)（之前的OpenAI Gym (opens in a new tab)）创建简单的代理-环境交互循环的示例。

```code

!pip install gymnasium

```

```code

import gymnasium as gym

import inspect

import tenacity

from langchain.chat_models import ChatOpenAI

from langchain.schema import (

AIMessage,

HumanMessage,

SystemMessage,

BaseMessage,

)

from langchain.output_parsers import RegexParser

```

定义代理#

```code

class GymnasiumAgent():

@classmethod

def get_docs(cls, env):

return env.unwrapped.__doc__

def __init__(self, model, env):

self.model = model

self.env = env

self.docs = self.get_docs(env)

self.instructions = """

Your goal is to maximize your return, i.e. the sum of the rewards you receive.

I will give you an observation, reward, terminiation flag, truncation flag, and the return so far, formatted as:

Observation: <observation>

Reward: <reward>

Termination: <termination>

Truncation: <truncation>

Return: <sum_of_rewards>

You will respond with an action, formatted as:

Action: <action>

where you replace <action> with your actual action.

Do nothing else but return the action.

"""

self.action_parser = RegexParser(

regex=r"Action: (.\*)",

output_keys=['action'],

default_output_key='action')

self.message_history = []

self.ret = 0

def random_action(self):

action = self.env.action_space.sample()

return action

def reset(self):

self.message_history = [

SystemMessage(content=self.docs),

SystemMessage(content=self.instructions),

]

def observe(self, obs, rew=0, term=False, trunc=False, info=None):

self.ret += rew

obs_message = f"""

Observation: {obs}

Reward: {rew}

Termination: {term}

Truncation: {trunc}

Return: {self.ret}

"""

self.message_history.append(HumanMessage(content=obs_message))

return obs_message

def _act(self):

act_message = self.model(self.message_history)

self.message_history.append(act_message)

action = int(self.action_parser.parse(act_message.content)['action'])

return action

def act(self):

try:

for attempt in tenacity.Retrying(

stop=tenacity.stop_after_attempt(2),

wait=tenacity.wait_none(),  # No waiting time between retries

retry=tenacity.retry_if_exception_type(ValueError),

before_sleep=lambda retry_state: print(f"ValueError occurred: {retry_state.outcome.exception()}, retrying..."),

):

with attempt:

action = self._act()

except tenacity.RetryError as e:

action = self.random_action()

return action

```

初始化模拟环境和代理#

```code

env = gym.make("Blackjack-v1")

agent = GymnasiumAgent(model=ChatOpenAI(temperature=0.2), env=env)

```

Main loop#

```code

observation, info = env.reset()

agent.reset()

obs_message = agent.observe(observation)

print(obs_message)

while True:

action = agent.act()

observation, reward, termination, truncation, info = env.step(action)

obs_message = agent.observe(observation, reward, termination, truncation, info)

print(f'Action: {action}')

print(obs_message)

if termination or truncation:

print('break', termination, truncation)

break

env.close()

```

```code

Observation: (15, 4, 0)

Reward: 0

Termination: False

Truncation: False

Return: 0

Action: 1

Observation: (25, 4, 0)

Reward: -1.0

Termination: True

Truncation: False

Return: -1.0

break True False

```
CharactersMulti Player Dnd


多人副本龙 DialogueAgent与地下城 DialogueSimulator – LangChain中文网

用例（User Case)智能体仿真（Agent Simulations）Multi Player Dnd

多人副本龙 DialogueAgent与地下城 DialogueSimulator
此文档演示了
```code
DialogueAgent
```
和
```code
DialogueSimulator
```
类如何轻松扩展 双人副本龙与地下城示例 (opens in a new tab) 至多个玩家。
模拟两名玩家和多个玩家之间的主要区别在于修订每个代理何时发言的时间表。
为此，我们增强了
```code
DialogueSimulator
```
，使其接收一个自定义函数来确定哪个代理讲话的时间表。在下面的示例中，每个角色以轮流的方式发言，每个玩家之间插入故事讲述者。
导入 LangChain 相关模块

```code

from typing import List, Dict, Callable

from langchain.chat_models import ChatOpenAI

from langchain.schema import (

AIMessage,

HumanMessage,

SystemMessage,

BaseMessage,

)

```

```code
DialogueAgent
```
类

```code
DialogueAgent
```
类是一个简单的包装器，包装了
```code
ChatOpenAI
```
模型，通过将消息串联为字符串来存储从
```code
dialogue_agent
```
视点的消息历史记录。
It exposes two methods:

```code
send()
```
: applies the chatmodel to the message history and returns the message string

```code
receive(name， message)
```
: 将
```code
name
```
说的
```code
message
```
添加到消息历史记录中

```code

class DialogueAgent:

def __init__(

self,

name: str,

system_message: SystemMessage,

model: ChatOpenAI,

) -> None:

self.name = name

self.system_message = system_message

self.model = model

self.prefix = f"{self.name}: "

self.reset()

def reset(self):

self.message_history = ["Here is the conversation so far."]

def send(self) -> str:

"""

Applies the chatmodel to the message history

and returns the message string

"""

message = self.model(

[

self.system_message,

HumanMessage(content="".join(self.message_history + [self.prefix])),

]

)

return message.content

def receive(self, name: str, message: str) -> None:

"""

Concatenates {message} spoken by {name} into message history

"""

self.message_history.append(f"{name}: {message}")

```

```code
DialogueSimulator
```
类#

```code
DialogueSimulator
```
类接受一个代理列表，并在每个步骤中执行以下操作:

选择下一个发言者
调用下一个发言者发送消息
将消息广播给所有其他代理
更新步数计数器。

下一个发言者的选择可以实现为任何函数，但在这种情况下，我们只需循环遍历代理即可。

```code

class DialogueSimulator:

def __init__(

self,

agents: List[DialogueAgent],

selection_function: Callable[[int, List[DialogueAgent]], int],

) -> None:

self.agents = agents

self._step = 0

self.select_next_speaker = selection_function

def reset(self):

for agent in self.agents:

agent.reset()

def inject(self, name: str, message: str):

"""

Initiates the conversation with a {message} from {name}

"""

for agent in self.agents:

agent.receive(name, message)

# increment time

self._step += 1

def step(self) -> tuple[str, str]:

# 1. choose the next speaker

speaker_idx = self.select_next_speaker(self._step, self.agents)

speaker = self.agents[speaker_idx]

# 2. next speaker sends message

message = speaker.send()

# 3. everyone receives message

for receiver in self.agents:

receiver.receive(speaker.name, message)

# 4. increment time

self._step += 1

return speaker.name, message

```

定义角色和任务#

```code

character_names = ["Harry Potter", "Ron Weasley", "Hermione Granger", "Argus Filch"]

storyteller_name = "Dungeon Master"

quest = "Find all of Lord Voldemort's seven horcruxes."

word_limit = 50 # word limit for task brainstorming

```

Ask an LLM to add detail to the game description#

```code

game_description = f"""Here is the topic for a Dungeons & Dragons game: {quest}.

The characters are: {\*character_names,}.

The story is narrated by the storyteller, {storyteller_name}."""

player_descriptor_system_message = SystemMessage(

content="You can add detail to the description of a Dungeons & Dragons player.")

def generate_character_description(character_name):

character_specifier_prompt = [

player_descriptor_system_message,

HumanMessage(content=

f"""{game_description}

Please reply with a creative description of the character, {character_name}, in {word_limit} words or less.

Speak directly to {character_name}.

Do not add anything else."""

)

]

character_description = ChatOpenAI(temperature=1.0)(character_specifier_prompt).content

return character_description

def generate_character_system_message(character_name, character_description):

return SystemMessage(content=(

f"""{game_description}

Your name is {character_name}.

Your character description is as follows: {character_description}.

You will propose actions you plan to take and {storyteller_name} will explain what happens when you take those actions.

Speak in the first person from the perspective of {character_name}.

For describing your own body movements, wrap your description in '\*'.

Do not change roles!

Do not speak from the perspective of anyone else.

Remember you are {character_name}.

Stop speaking the moment you finish speaking from your perspective.

Never forget to keep your response to {word_limit} words!

Do not add anything else.

"""

))

character_descriptions = [generate_character_description(character_name) for character_name in character_names]

character_system_messages = [generate_character_system_message(character_name, character_description) for character_name, character_description in zip(character_names, character_descriptions)]

storyteller_specifier_prompt = [

player_descriptor_system_message,

HumanMessage(content=

f"""{game_description}

Please reply with a creative description of the storyteller, {storyteller_name}, in {word_limit} words or less.

Speak directly to {storyteller_name}.

Do not add anything else."""

)

]

storyteller_description = ChatOpenAI(temperature=1.0)(storyteller_specifier_prompt).content

storyteller_system_message = SystemMessage(content=(

f"""{game_description}

You are the storyteller, {storyteller_name}.

Your description is as follows: {storyteller_description}.

The other players will propose actions to take and you will explain what happens when they take those actions.

Speak in the first person from the perspective of {storyteller_name}.

Do not change roles!

Do not speak from the perspective of anyone else.

Remember you are the storyteller, {storyteller_name}.

Stop speaking the moment you finish speaking from your perspective.

Never forget to keep your response to {word_limit} words!

Do not add anything else.

"""

))

```

```code

print('Storyteller Description:')

print(storyteller_description)

for character_name, character_description in zip(character_names, character_descriptions):

print(f'{character_name} Description:')

print(character_description)

```

```code

Storyteller Description:

Dungeon Master, your power over this adventure is unparalleled. With your whimsical mind and impeccable storytelling, you guide us through the dangers of Hogwarts and beyond. We eagerly await your every twist, your every turn, in the hunt for Voldemort's cursed horcruxes.

Harry Potter Description:

"Welcome, Harry Potter. You are the young wizard with a lightning-shaped scar on your forehead. You possess brave and heroic qualities that will be essential on this perilous quest. Your destiny is not of your own choosing, but you must rise to the occasion and destroy the evil horcruxes. The wizarding world is counting on you."

Ron Weasley Description:

Ron Weasley, you are Harry's loyal friend and a talented wizard. You have a good heart but can be quick to anger. Keep your emotions in check as you journey to find the horcruxes. Your bravery will be tested, stay strong and focused.

Hermione Granger Description:

Hermione Granger, you are a brilliant and resourceful witch, with encyclopedic knowledge of magic and an unwavering dedication to your friends. Your quick thinking and problem-solving skills make you a vital asset on any quest.

Argus Filch Description:

Argus Filch, you are a squib, lacking magical abilities. But you make up for it with your sharpest of eyes, roving around the Hogwarts castle looking for any rule-breaker to punish. Your love for your feline friend, Mrs. Norris, is the only thing that feeds your heart.

```

使用一个 LLM 创建一个详细的任务描述#

```code
quest_specifier_prompt = [

SystemMessage(content="You can make a task more specific."),

HumanMessage(content=

f"""{game_description}

You are the storyteller, {storyteller_name}.

Please make the quest more specific. Be creative and imaginative.

Please reply with the specified quest in {word_limit} words or less.

Speak directly to the characters: {\*character_names,}.

Do not add anything else."""

)

]

specified_quest = ChatOpenAI(temperature=1.0)(quest_specifier_prompt).content

print(f"Original quest:{quest}")

print(f"Detailed quest:{specified_quest}")

```

```code
Original quest:

Find all of Lord Voldemort's seven horcruxes.

Detailed quest:

Harry Potter and his companions must journey to the Forbidden Forest, find the hidden entrance to Voldemort's secret lair, and retrieve the horcrux guarded by the deadly Acromantula, Aragog. Remember, time is of the essence as Voldemort's power grows stronger every day. Good luck.

```

主循环#

```code
characters = []

for character_name, character_system_message in zip(character_names, character_system_messages):

characters.append(DialogueAgent(

name=character_name,

system_message=character_system_message,

model=ChatOpenAI(temperature=0.2)))

storyteller = DialogueAgent(name=storyteller_name,

system_message=storyteller_system_message,

model=ChatOpenAI(temperature=0.2))

```

```code
def select_next_speaker(step: int, agents: List[DialogueAgent]) -> int:

"""

If the step is even, then select the storyteller

Otherwise, select the other characters in a round-robin fashion.

For example, with three characters with indices: 1 2 3

The storyteller is index 0.

Then the selected index will be as follows:

step: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

idx: 0 1 0 2 0 3 0 1 0 2 0 3 0 1 0 2 0

"""

if step % 2 == 0:

idx = 0

else:

idx = (step//2) % (len(agents)-1) + 1

return idx

```

```code
max_iters = 20

n = 0

simulator = DialogueSimulator(

agents=[storyteller] + characters,

selection_function=select_next_speaker

)

simulator.reset()

simulator.inject(storyteller_name, specified_quest)

print(f"({storyteller_name}): {specified_quest}")

print('')

while n < max_iters:

name, message = simulator.step()

print(f"({name}): {message}")

print('')

n += 1

```

```code
(Dungeon Master): Harry Potter and his companions must journey to the Forbidden Forest, find the hidden entrance to Voldemort's secret lair, and retrieve the horcrux guarded by the deadly Acromantula, Aragog. Remember, time is of the essence as Voldemort's power grows stronger every day. Good luck.

(Harry Potter): I suggest we sneak into the Forbidden Forest under the cover of darkness. Ron, Hermione, and I can use our wands to create a Disillusionment Charm to make us invisible. Filch, you can keep watch for any signs of danger. Let's move quickly and quietly.

(Dungeon Master): As you make your way through the Forbidden Forest, you hear the eerie sounds of nocturnal creatures. Suddenly, you come across a clearing where Aragog and his spider minions are waiting for you. Ron, Hermione, and Harry, you must use your wands to cast spells to fend off the spiders while Filch keeps watch. Be careful not to get bitten!

(Ron Weasley): I'll cast a spell to create a fiery blast to scare off the spiders. *I wave my wand and shout "Incendio!"* Hopefully, that will give us enough time to find the horcrux and get out of here safely.

(Dungeon Master): Ron's spell creates a burst of flames, causing the spiders to scurry away in fear. You quickly search the area and find a small, ornate box hidden in a crevice. Congratulations, you have found one of Voldemort's horcruxes! But beware, the Dark Lord's minions will stop at nothing to get it back.

(Hermione Granger): We need to destroy this horcrux as soon as possible. I suggest we use the Sword of Gryffindor to do it. Harry, do you still have it with you? We can use Fiendfyre to destroy it, but we need to be careful not to let the flames get out of control. Ron, can you help me create a protective barrier around us while Harry uses the sword?

(Dungeon Master): Harry retrieves the Sword of Gryffindor from his bag and holds it tightly. Hermione and Ron cast a protective barrier around the group as Harry uses the sword to destroy the horcrux with a swift strike. The box shatters into a million pieces, and a dark energy dissipates into the air. Well done, but there are still six more horcruxes to find and destroy. The hunt continues.

(Argus Filch): *I keep watch, making sure no one is following us.* I'll also keep an eye out for any signs of danger. Mrs. Norris, my trusty companion, will help me sniff out any trouble. We'll make sure the group stays safe while they search for the remaining horcruxes.

(Dungeon Master): As you continue on your quest, Filch and Mrs. Norris alert you to a group of Death Eaters approaching. You must act quickly to defend yourselves. Harry, Ron, and Hermione, use your wands to cast spells while Filch and Mrs. Norris keep watch. Remember, the fate of the wizarding world rests on your success.

(Harry Potter): I'll cast a spell to create a shield around us. *I wave my wand and shout "Protego!"* Ron and Hermione, you focus on attacking the Death Eaters with your spells. We need to work together to defeat them and protect the remaining horcruxes. Filch, keep watch and let us know if there are any more approaching.

(Dungeon Master): Harry's shield protects the group from the Death Eaters' spells as Ron and Hermione launch their own attacks. The Death Eaters are no match for the combined power of the trio and are quickly defeated. You continue on your journey, knowing that the next horcrux could be just around the corner. Keep your wits about you, for the Dark Lord's minions are always watching.

(Ron Weasley): I suggest we split up to cover more ground. Harry and I can search the Forbidden Forest while Hermione and Filch search Hogwarts. We can use our wands to communicate with each other and meet back up once we find a horcrux. Let's move quickly and stay alert for any danger.

(Dungeon Master): As the group splits up, Harry and Ron make their way deeper into the Forbidden Forest while Hermione and Filch search the halls of Hogwarts. Suddenly, Harry and Ron come across a group of dementors. They must use their Patronus charms to fend them off while Hermione and Filch rush to their aid. Remember, the power of friendship and teamwork is crucial in this quest.

(Hermione Granger): I hear Harry and Ron's Patronus charms from afar. We need to hurry and help them. Filch, can you use your knowledge of Hogwarts to find a shortcut to their location? I'll prepare a spell to repel the dementors. We need to work together to protect each other and find the next horcrux.

(Dungeon Master): Filch leads Hermione to a hidden passageway that leads to Harry and Ron's location. Hermione's spell repels the dementors, and the group is reunited. They continue their search, knowing that every moment counts. The fate of the wizarding world rests on their success.

(Argus Filch): *I keep watch as the group searches for the next horcrux.* Mrs. Norris and I will make sure no one is following us. We need to stay alert and work together to find the remaining horcruxes before it's too late. The Dark Lord's power grows stronger every day, and we must not let him win.

(Dungeon Master): As the group continues their search, they come across a hidden room in the depths of Hogwarts. Inside, they find a locket that they suspect is another one of Voldemort's horcruxes. But the locket is cursed, and they must work together to break the curse before they can destroy it. Harry, Ron, and Hermione, use your combined knowledge and skills to break the curse while Filch and Mrs. Norris keep watch. Time is running out, and the fate of the wizarding world rests on your success.

(Harry Potter): I'll use my knowledge of dark magic to try and break the curse on the locket. Ron and Hermione, you can help me by using your wands to channel your magic into mine. We need to work together and stay focused. Filch, keep watch and let us know if there are any signs of danger.

Dungeon Master: Harry, Ron, and Hermione combine their magical abilities to break the curse on the locket. The locket opens, revealing a small piece of Voldemort's soul. Harry uses the Sword of Gryffindor to destroy it, and the group feels a sense of relief knowing that they are one step closer to defeating the Dark Lord. But there are still four more horcruxes to find and destroy. The hunt continues.

(Dungeon Master): As the group continues their quest, they face even greater challenges and dangers. But with their unwavering determination and teamwork, they press on, knowing that the fate of the wizarding world rests on their success. Will they be able to find and destroy all of Voldemort's horcruxes before it's too late? Only time will tell.

(Ron Weasley): We can't give up now. We've come too far to let Voldemort win. Let's keep searching and fighting until we destroy all of his horcruxes and defeat him once and for all. We can do this together.

(Dungeon Master): The group nods in agreement, their determination stronger than ever. They continue their search, facing challenges and obstacles at every turn. But they know that they must not give up, for the fate of the wizarding world rests on their success. The hunt for Voldemort's horcruxes continues, and the end is in sight.

```
GymnasiumMultiagent Authoritarian