提取（Extraction） – LangChain中文网

用例（User Case)提取（Extraction）

提取（Extraction）

概念指南 (opens in a new tab)

大多数API和数据库仍然处理结构化信息。因此，为了更好地与这些信息一起工作，从文本中提取结构化信息可能是有用的。其中的例子包括：

从句子中提取一个结构化行以插入到数据库中
从长文档中提取多行以插入到数据库中
从用户查询中提取正确的API参数

这项工作与输出解析密切相关。
输出解析器负责指示LLM以特定格式响应。
在这种情况下，输出解析器指定您想要从文档中提取的数据的格式。然后，除了输出格式指令之外，提示应该还包括执行提取操作所需的指令。虽然常规的输出解析器对于响应数据的基本结构化已经足够好了，
但在进行提取时，您经常需要提取更复杂或嵌套的结构。
如果想深入了解提取，请查看
```code
kor
```
(opens in a new tab)，
这个库使用现有的LangChain链和OutputParser抽象，
但深入研究了允许提取更复杂的模式。基于 Chinook 的 SQL 问答基准测试 SQL QA Benchmarking Chinook个人助手（Personal Assistants）


个人助手（Personal Assistants） – LangChain中文网

用例（User Case)个人助手（Personal Assistants）

个人助手（Personal Assistants）

概念指南 (opens in a new tab)

我们在这里使用“个人助理”这个词语的意思非常广泛。个人助理具有以下几个特征：

它们可以与外部世界交互
它们了解您的数据
它们记住您的交互

实际上，LangChain中的所有功能都与构建个人助理有关。以下是特定部分的重点：

代理文档
（用于与外部世界交互）
索引文档
（为它们提供数据知识）
内存
（帮助它们记住交互）

具体例子包括：

AI插件
插件式AI（插件数据库）：一个实现了插件检索和使用的代理程序。
Wikibase代理程序：一个与Wikibase交互的代理程序实现。
销售GPT：本笔记演示了一个上下文感知的AI销售代理实现。
提取（Extraction）问答（Question Answering）


问答（Question Answering） – LangChain中文网

用例（User Case)问答（Question Answering）

问答（Question Answering）

概念指南 (opens in a new tab)

在此上下文中，问答指的是在文档数据上进行的问答。
对于其他类型数据的问答，请参考其他来源的文档，如
SQL 数据库问答
或
与 API 交互。
对于许多文档的问答，您几乎总是希望在数据上创建索引。
这可以用于智能地访问给定问题的最相关文档，从而避免将所有文档传递给 LLM（节省时间和金钱）。
有关更详细的介绍，请参见
此教程，
但对于超级快速启动，步骤涉及：加载文档

```code
from langchain.document_loaders import TextLoader
loader = TextLoader('../state_of_the_union.txt')
```

在这里查看更多有关如何开始文档加载的信息。
创建索引

```code
from langchain.indexes import VectorstoreIndexCreator
index = VectorstoreIndexCreator().from_loaders([loader])
```

目前最好、最流行的索引是VectorStore索引。
查询您的索引

```code
query = "What did the president say about Ketanji Brown Jackson"
index.query(query)
```

或者，使用
```code
query_with_sources
```
也可以返回所涉及的来源。

```code
query = "What did the president say about Ketanji Brown Jackson"
index.query_with_sources(query)
```

同样，这些高级接口掩盖了许多在幕后发生的事情，请参见这里，以获取有关如何开始的更多信息，降低纬度理解它。
文档问答
文档问答涉及获取多个文档，然后对它们提出问题。LLM响应将根据文档内容包含您问题的答案。
使用问答链的推荐方法是：

```code
from langchain.chains.question_answering import load_qa_chain
chain = load_qa_chain(llm, chain_type="stuff")
chain.run(input_documents=docs, question=query)

```

以下资源可用：

问答教程：演示如何完成此任务的教程。
VectorDB问答教程：演示如何对VectorDB执行问答的教程。一个向量数据库。当你有大量文档时，这通常很有用，你不想将它们全部传递给LLM，而是想先对嵌入进行一些语义搜索。

添加来源
还有一种变体，除了回答之外，语言模型还会引用它的来源（比如使用了哪些传递给它的文档）。
使用带有来源的问答链进行起步的推荐方法是：

```code
from langchain.chains.qa_with_sources import load_qa_with_sources_chain
chain = load_qa_with_sources_chain(llm, chain_type="stuff")
chain({"input_documents": docs, "question": query}, return_only_outputs=True)

```

以下资源可用：

带来源的问答教程：一个演示如何使用带有来源的问答链的教程。成此任务的方法。

VectorDB QA With Sources Notebook：一份教程，介绍如何在向量数据库上使用源进行问答。当您有大量文档时，您可能不想将它们全部传递给LLM，而是想先对嵌入进行一些语义搜索，这时候这个方法通常非常有用。

其他相关资源
#
其他相关资源包括：

用于处理文档的实用工具：指南介绍了几个实用的工具，对于此任务非常有帮助，包括文本分割器（用于分割长文档）和嵌入和向量存储（对上述向量数据库示例非常有用）。

CombineDocuments Chains：介绍了特定类型的链的概念概述，您可以使用这些链完成此任务。端到端示例
#

要查看以端到端方式完成的示例
请参阅以下资源：

使用Sources Notebook对群聊进行语义搜索：一个教程，可在群聊对话中进行语义搜索。
个人助手（Personal Assistants）Semantic Search over Chat


在群聊消息中进行问题回答# – LangChain中文网

用例（User Case)问答（Question Answering）Semantic Search over Chat

在群聊消息中进行问题回答#
在本教程中，我们将使用Langchain + Deep Lake和GPT4来语义搜索和提问群组聊天。
在此处查看工作演示[此处]（https://twitter.com/thisissukh_/status/1647223328363679745） (opens in a new tab)
安装所需的软件包#

```code

!python3 -m pip install --upgrade langchain deeplake openai tiktoken

```

添加 API 密钥 Add API keys#

```code

import os

import getpass

from langchain.document_loaders import PyPDFLoader, TextLoader

from langchain.embeddings.openai import OpenAIEmbeddings

from langchain.text_splitter import RecursiveCharacterTextSplitter, CharacterTextSplitter

from langchain.vectorstores import DeepLake

from langchain.chains import ConversationalRetrievalChain, RetrievalQA

from langchain.chat_models import ChatOpenAI

from langchain.llms import OpenAI

os.environ['OPENAI_API_KEY'] = getpass.getpass('OpenAI API Key:')

os.environ['ACTIVELOOP_TOKEN'] = getpass.getpass('Activeloop Token:')

os.environ['ACTIVELOOP_ORG'] = getpass.getpass('Activeloop Org:')

org = os.environ['ACTIVELOOP_ORG']

embeddings = OpenAIEmbeddings()

dataset_path = 'hub://' + org + '/data'

```

创建样本数据 Create sample data#
您可以使用ChatGPT使用此提示生成示例群聊会话:。

```code

Generate a group chat conversation with three friends talking about their day, referencing real places and fictional names. Make it funny and as detailed as possible.

```

我已经生成了这样的聊天
```code
messages.txt
```
。 我们可以保持简单，使用这个作为我们的例子。

摄取聊天嵌入 Ingest chat embeddings#

我们将消息加载到文本文件中，分块并上传到 ActiveLoop Vector 存储。

```code

with open("messages.txt") as f:

state_of_the_union = f.read()

text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)

pages = text_splitter.split_text(state_of_the_union)

text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)

texts = text_splitter.create_documents(pages)

print (texts)

dataset_path = 'hub://'+org+'/data'

embeddings = OpenAIEmbeddings()

db = DeepLake.from_documents(texts, embeddings, dataset_path=dataset_path, overwrite=True)

```

问问题 Ask questions#

现在我们可以提出一个问题并通过语义搜索得到答案:

```code

db = DeepLake(dataset_path=dataset_path, read_only=True, embedding_function=embeddings)

retriever = db.as_retriever()

retriever.search_kwargs['distance_metric'] = 'cos'

retriever.search_kwargs['k'] = 4

qa = RetrievalQA.from_chain_type(llm=OpenAI(), chain_type="stuff", retriever=retriever, return_source_documents=False)

# What was the restaurant the group was talking about called?

query = input("Enter query:")

# The Hungry Lobster

ans = qa({"query": query})

print(ans)

```
问答（Question Answering）摘要（Summarization）


摘要（Summarization） – LangChain中文网

用例（User Case)摘要（Summarization）

摘要（Summarization）
摘要生成涉及创建多个较长文档的较小摘要。这对于将长文档蒸馏为核心信息非常有用。
建议使用摘要链的方法是：

```code
from langchain.chains.summarize import load_summarize_chain
chain = load_summarize_chain(llm, chain_type="map_reduce")
chain.run(docs)
```

存在以下资源：

摘要教程Summarization Notebook：演示如何完成此任务的教程。

其他相关的资源还包括：

指南介绍了一些实用程序的使用方法，这些实用程序对于完成该任务非常有帮助，包括文本拆分，使用分割器（用于拆分长文档）。
Semantic Search over Chat表格（Tabular）


表格（Tabular） – LangChain中文网

用例（User Case)表格（Tabular）

表格（Tabular）
很多数据和信息都存储在表格数据中，无论是csv、excel表格还是SQL表格。本页面涵盖了LangChain中用于处理此类格式数据的所有资源。
文档加载
如果您有以表格格式存储的文本数据，您可能希望将数据加载到文档中，然后像处理其他文本/非结构化数据一样对其进行索引。
为此，您应该使用类似CSVLoader的文档加载器，
然后创建一个覆盖该数据的索引，并以这种方式进行查询。
如果您有更多的数字表格数据，或者有大量数据而不想对其进行索引，您应该开始查看我们处理此数据的各种链和代理。
链
如果您刚开始，有相对较小/简单的表格数据，那么您应该从链开始。链是一系列预定步骤，因此它们很适合入门，因为它们能够给您更多的控制并让您更好地理解所发生的情况。

SQL 数据库链

代理
代理更加复杂，涉及多个查询到 LLM 以了解要执行的操作。代理的缺点是您的控制力较少，但优点是它们可以处理更复杂的数据和查询。以下是翻译后的内容：
这里列出了三个代理工具的链接，它们是SQL Agent、Pandas Agent和CSV Agent。它们比较强大，可以在更大的数据库和更复杂的模式上使用。

SQL Agent
Pandas Agent
CSV Agent
摘要（Summarization）Baby Agi


BabyAGI用户指南# – LangChain中文网

用例（User Case)agentsBaby Agi

BabyAGI用户指南#
本文档演示了如何由Yohei Nakajima (opens in a new tab)创建的BabyAGI (opens in a new tab)。 BabyAGI是一个AI代理，可以基于给定的目标生成并假装执行任务。
本指南将帮助您了解创建您自己的递归代理程序的组件。
尽管BabyAGI使用特定的向量存储库/模型提供程序（Pinecone，OpenAI），之一实施它使用LangChain的好处是您可以轻松地为不同选项更换它们。在此实现中，我们使用FAISS向量存储库（因为它在本地运行并且免费）。
安装并导入所需模块#

```code
import os

from collections import deque

from typing import Dict, List, Optional, Any

from langchain import LLMChain, OpenAI, PromptTemplate

from langchain.embeddings import OpenAIEmbeddings

from langchain.llms import BaseLLM

from langchain.vectorstores.base import VectorStore

from pydantic import BaseModel, Field

from langchain.chains.base import Chain

```

连接向量存储库#
根据您使用的向量存储库，此步骤可能会有所不同。

```code
from langchain.vectorstores import FAISS

from langchain.docstore import InMemoryDocstore

```

```code
# Define your embedding model

embeddings_model = OpenAIEmbeddings()

# Initialize the vectorstore as empty

import faiss

embedding_size = 1536

index = faiss.IndexFlatL2(embedding_size)

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

```

定义链 Define the Chains#

BabyAGI依赖于三个LLM链:

任务创建链，用于选择要添加到列表中的新任务
任务优先级链，用于重新设置任务的优先级
执行链，用于执行任务

```code
class TaskCreationChain(LLMChain):

"""Chain to generates tasks."""

@classmethod

def from_llm(cls, llm: BaseLLM, verbose: bool = True) -> LLMChain:

"""Get the response parser."""

task_creation_template = (

"You are a task creation AI that uses the result of an execution agent"

" to create new tasks with the following objective: {objective},"

" The last completed task has the result: {result}."

" This result was based on this task description: {task_description}."

" These are incomplete tasks: {incomplete_tasks}."

" Based on the result, create new tasks to be completed"

" by the AI system that do not overlap with incomplete tasks."

" Return the tasks as an array."

)

prompt = PromptTemplate(

template=task_creation_template,

input_variables=[

"result",

"task_description",

"incomplete_tasks",

"objective",

],

)

return cls(prompt=prompt, llm=llm, verbose=verbose)

```

```code
class TaskPrioritizationChain(LLMChain):

"""Chain to prioritize tasks."""

@classmethod

def from_llm(cls, llm: BaseLLM, verbose: bool = True) -> LLMChain:

"""Get the response parser."""

task_prioritization_template = (

"You are a task prioritization AI tasked with cleaning the formatting of and reprioritizing"

" the following tasks: {task_names}."

" Consider the ultimate objective of your team: {objective}."

" Do not remove any tasks. Return the result as a numbered list, like:"

" #. First task"

" #. Second task"

" Start the task list with number {next_task_id}."

)

prompt = PromptTemplate(

template=task_prioritization_template,

input_variables=["task_names", "next_task_id", "objective"],

)

return cls(prompt=prompt, llm=llm, verbose=verbose)

```

```code
class ExecutionChain(LLMChain):

"""Chain to execute tasks."""

@classmethod

def from_llm(cls, llm: BaseLLM, verbose: bool = True) -> LLMChain:

"""Get the response parser."""

execution_template = (

"You are an AI who performs one task based on the following objective: {objective}."

" Take into account these previously completed tasks: {context}."

" Your task: {task}."

" Response:"

)

prompt = PromptTemplate(

template=execution_template,

input_variables=["objective", "context", "task"],

)

return cls(prompt=prompt, llm=llm, verbose=verbose)

```

定义BabyAGI控制器#
BabyAGI将以上定义的链组合成（可能是）无限循环。

```code
def get_next_task(

task_creation_chain: LLMChain,

result: Dict,

task_description: str,

task_list: List[str],

objective: str,

) -> List[Dict]:

"""Get the next task."""

incomplete_tasks = ", ".join(task_list)

response = task_creation_chain.run(

result=result,

task_description=task_description,

incomplete_tasks=incomplete_tasks,

objective=objective,

)

new_tasks = response.split("")

return [{"task_name": task_name} for task_name in new_tasks if task_name.strip()]

```

```code
def prioritize_tasks(

task_prioritization_chain: LLMChain,

this_task_id: int,

task_list: List[Dict],

objective: str,

) -> List[Dict]:

"""Prioritize tasks."""

task_names = [t["task_name"] for t in task_list]

next_task_id = int(this_task_id) + 1

response = task_prioritization_chain.run(

task_names=task_names, next_task_id=next_task_id, objective=objective

)

new_tasks = response.split("")

prioritized_task_list = []

for task_string in new_tasks:

if not task_string.strip():

continue

task_parts = task_string.strip().split(".", 1)

if len(task_parts) == 2:

task_id = task_parts[0].strip()

task_name = task_parts[1].strip()

prioritized_task_list.append({"task_id": task_id, "task_name": task_name})

return prioritized_task_list

```

```code
def _get_top_tasks(vectorstore, query: str, k: int) -> List[str]:

"""Get the top k tasks based on the query."""

results = vectorstore.similarity_search_with_score(query, k=k)

if not results:

return []

sorted_results, _ = zip(*sorted(results, key=lambda x: x[1], reverse=True))

return [str(item.metadata["task"]) for item in sorted_results]

def execute_task(

vectorstore, execution_chain: LLMChain, objective: str, task: str, k: int = 5

) -> str:

"""Execute a task."""

context = _get_top_tasks(vectorstore, query=objective, k=k)

return execution_chain.run(objective=objective, context=context, task=task)

```

```code
class BabyAGI(Chain, BaseModel):

"""Controller model for the BabyAGI agent."""

task_list: deque = Field(default_factory=deque)

task_creation_chain: TaskCreationChain = Field(...)

task_prioritization_chain: TaskPrioritizationChain = Field(...)

execution_chain: ExecutionChain = Field(...)

task_id_counter: int = Field(1)

vectorstore: VectorStore = Field(init=False)

max_iterations: Optional[int] = None

class Config:

"""Configuration for this pydantic object."""

arbitrary_types_allowed = True

def add_task(self, task: Dict):

self.task_list.append(task)

def print_task_list(self):

print("\033[95m\033[1m" + "*****TASK LIST*****" + "\033[0m\033[0m")

for t in self.task_list:

print(str(t["task_id"]) + ": " + t["task_name"])

def print_next_task(self, task: Dict):

print("\033[92m\033[1m" + "*****NEXT TASK*****" + "\033[0m\033[0m")

print(str(task["task_id"]) + ": " + task["task_name"])

def print_task_result(self, result: str):

print("\033[93m\033[1m" + "*****TASK RESULT*****" + "\033[0m\033[0m")

print(result)

@property

def input_keys(self) -> List[str]:

return ["objective"]

@property

def output_keys(self) -> List[str]:

return []

def _call(self, inputs: Dict[str, Any]) -> Dict[str, Any]:

"""Run the agent."""

objective = inputs["objective"]

first_task = inputs.get("first_task", "Make a todo list")

self.add_task({"task_id": 1, "task_name": first_task})

num_iters = 0

while True:

if self.task_list:

self.print_task_list()

# Step 1: Pull the first task

task = self.task_list.popleft()

self.print_next_task(task)

# Step 2: Execute the task

result = execute_task(

self.vectorstore, self.execution_chain, objective, task["task_name"]

)

this_task_id = int(task["task_id"])

self.print_task_result(result)

# Step 3: Store the result in Pinecone

result_id = f"result_{task['task_id']}"

self.vectorstore.add_texts(

texts=[result],

metadatas=[{"task": task["task_name"]}],

ids=[result_id],

)

# Step 4: Create new tasks and reprioritize task list

new_tasks = get_next_task(

self.task_creation_chain,

result,

task["task_name"],

[t["task_name"] for t in self.task_list],

objective,

)

for new_task in new_tasks:

self.task_id_counter += 1

new_task.update({"task_id": self.task_id_counter})

self.add_task(new_task)

self.task_list = deque(

prioritize_tasks(

self.task_prioritization_chain,

this_task_id,

list(self.task_list),

objective,

)

)

num_iters += 1

if self.max_iterations is not None and num_iters == self.max_iterations:

print(

"\033[91m\033[1m" + "*****TASK ENDING*****" + "\033[0m\033[0m"

)

break

return {}

@classmethod

def from_llm(

cls, llm: BaseLLM, vectorstore: VectorStore, verbose: bool = False, **kwargs

) -> "BabyAGI":

"""Initialize the BabyAGI Controller."""

task_creation_chain = TaskCreationChain.from_llm(llm, verbose=verbose)

task_prioritization_chain = TaskPrioritizationChain.from_llm(

llm, verbose=verbose

)

execution_chain = ExecutionChain.from_llm(llm, verbose=verbose)

return cls(

task_creation_chain=task_creation_chain,

task_prioritization_chain=task_prioritization_chain,

execution_chain=execution_chain,

vectorstore=vectorstore,

**kwargs,

)

```

运行BabyAGI#
现在该创建BabyAGI控制器并观察其尝试完成您的目标了。

```code
OBJECTIVE = "Write a weather report for SF today"

```

```code
llm = OpenAI(temperature=0)

```

```code
# Logging of LLMChains

verbose = False

# If None, will keep on going forever

max_iterations: Optional[int] = 3

baby_agi = BabyAGI.from_llm(

llm=llm, vectorstore=vectorstore, verbose=verbose, max_iterations=max_iterations

)

```

```code
baby_agi({"objective": OBJECTIVE})

```

```code

*****TASK LIST*****

1: Make a todo list

*****NEXT TASK*****

1: Make a todo list

*****TASK RESULT*****

1. Check the temperature range for the day.

2. Gather temperature data for SF today.

3. Analyze the temperature data and create a weather report.

4. Publish the weather report.

*****TASK LIST*****

2: Gather data on the expected temperature range for the day.

3: Collect data on the expected precipitation for the day.

4: Analyze the data and create a weather report.

5: Check the current weather conditions in SF.

6: Publish the weather report.

*****NEXT TASK*****

2: Gather data on the expected temperature range for the day.

*****TASK RESULT*****

I have gathered data on the expected temperature range for the day in San Francisco. The forecast is for temperatures to range from a low of 55 degrees Fahrenheit to a high of 68 degrees Fahrenheit.

*****TASK LIST*****

3: Check the current weather conditions in SF.

4: Calculate the average temperature for the day in San Francisco.

5: Determine the probability of precipitation for the day in San Francisco.

6: Identify any potential weather warnings or advisories for the day in San Francisco.

7: Research any historical weather patterns for the day in San Francisco.

8: Compare the expected temperature range to the historical average for the day in San Francisco.

9: Collect data on the expected precipitation for the day.

10: Analyze the data and create a weather report.

11: Publish the weather report.

*****NEXT TASK*****

3: Check the current weather conditions in SF.

*****TASK RESULT*****

I am checking the current weather conditions in SF. According to the data I have gathered, the temperature in SF today is currently around 65 degrees Fahrenheit with clear skies. The temperature range for the day is expected to be between 60 and 70 degrees Fahrenheit.

*****TASK ENDING*****

```

```code
{'objective': 'Write a weather report for SF today'}

```
表格（Tabular）Baby Agi with Agent


BabyAGI带工具# – LangChain中文网

用例（User Case)agentsBaby Agi with Agent

BabyAGI带工具#
本文档基于baby agi，，但演示了如何更换执行链。之前的执行链只是一个LLM，胡编乱造。通过用具有工具访问权限的代理替换它，我们可以希望获得真正可靠的信息
安装和导入所需模块#

```code

import os

from collections import deque

from typing import Dict, List, Optional, Any

from langchain import LLMChain, OpenAI, PromptTemplate

from langchain.embeddings import OpenAIEmbeddings

from langchain.llms import BaseLLM

from langchain.vectorstores.base import VectorStore

from pydantic import BaseModel, Field

from langchain.chains.base import Chain

```

连接到向量存储#
根据您使用的向量存储方式，此步骤可能看起来不同。

```code

%pip install faiss-cpu > /dev/null

%pip install google-search-results > /dev/null

from langchain.vectorstores import FAISS

from langchain.docstore import InMemoryDocstore

```

```code

# Define your embedding model

embeddings_model = OpenAIEmbeddings()

# Initialize the vectorstore as empty

import faiss

embedding_size = 1536

index = faiss.IndexFlatL2(embedding_size)

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

```

定义链#
BabyAGI依赖于三个LLM链:

任务创建链以选择要添加到列表中的新任务
任务优先级链以重新设置任务优先级
执行链执行任务

注意: 在这本笔记中，执行链将会变成代理。

```code

class TaskCreationChain(LLMChain):

"""Chain to generates tasks."""

@classmethod

def from_llm(cls, llm: BaseLLM, verbose: bool = True) -> LLMChain:

"""Get the response parser."""

task_creation_template = (

"You are an task creation AI that uses the result of an execution agent"

" to create new tasks with the following objective: {objective},"

" The last completed task has the result: {result}."

" This result was based on this task description: {task_description}."

" These are incomplete tasks: {incomplete_tasks}."

" Based on the result, create new tasks to be completed"

" by the AI system that do not overlap with incomplete tasks."

" Return the tasks as an array."

)

prompt = PromptTemplate(

template=task_creation_template,

input_variables=[

"result",

"task_description",

"incomplete_tasks",

"objective",

],

)

return cls(prompt=prompt, llm=llm, verbose=verbose)

```

```code

class TaskPrioritizationChain(LLMChain):

"""Chain to prioritize tasks."""

@classmethod

def from_llm(cls, llm: BaseLLM, verbose: bool = True) -> LLMChain:

"""Get the response parser."""

task_prioritization_template = (

"You are an task prioritization AI tasked with cleaning the formatting of and reprioritizing"

" the following tasks: {task_names}."

" Consider the ultimate objective of your team: {objective}."

" Do not remove any tasks. Return the result as a numbered list, like:"

" #. First task"

" #. Second task"

" Start the task list with number {next_task_id}."

)

prompt = PromptTemplate(

template=task_prioritization_template,

input_variables=["task_names", "next_task_id", "objective"],

)

return cls(prompt=prompt, llm=llm, verbose=verbose)

```

```code

from langchain.agents import ZeroShotAgent, Tool, AgentExecutor

from langchain import OpenAI, SerpAPIWrapper, LLMChain

todo_prompt = PromptTemplate.from_template(

"You are a planner who is an expert at coming up with a todo list for a given objective. Come up with a todo list for this objective: {objective}"

)

todo_chain = LLMChain(llm=OpenAI(temperature=0), prompt=todo_prompt)

search = SerpAPIWrapper()

tools = [

Tool(

name="Search",

func=search.run,

description="useful for when you need to answer questions about current events",

),

Tool(

name="TODO",

func=todo_chain.run,

description="useful for when you need to come up with todo lists. Input: an objective to create a todo list for. Output: a todo list for that objective. Please be very clear what the objective is!",

),

]

prefix = """You are an AI who performs one task based on the following objective: {objective}. Take into account these previously completed tasks: {context}."""

suffix = """Question: {task}

{agent_scratchpad}"""

prompt = ZeroShotAgent.create_prompt(

tools,

prefix=prefix,

suffix=suffix,

input_variables=["objective", "task", "context", "agent_scratchpad"],

)

```

定义BabyAGI控制器#
BabyAGI将在一个（可能是无限循环的）循环中组合上面定义的链。

```code

def get_next_task(

task_creation_chain: LLMChain,

result: Dict,

task_description: str,

task_list: List[str],

objective: str,

) -> List[Dict]:

"""Get the next task."""

incomplete_tasks = ", ".join(task_list)

response = task_creation_chain.run(

result=result,

task_description=task_description,

incomplete_tasks=incomplete_tasks,

objective=objective,

)

new_tasks = response.split("")

return [{"task_name": task_name} for task_name in new_tasks if task_name.strip()]

```

```code

def prioritize_tasks(

task_prioritization_chain: LLMChain,

this_task_id: int,

task_list: List[Dict],

objective: str,

) -> List[Dict]:

"""Prioritize tasks."""

task_names = [t["task_name"] for t in task_list]

next_task_id = int(this_task_id) + 1

response = task_prioritization_chain.run(

task_names=task_names, next_task_id=next_task_id, objective=objective

)

new_tasks = response.split("")

prioritized_task_list = []

for task_string in new_tasks:

if not task_string.strip():

continue

task_parts = task_string.strip().split(".", 1)

if len(task_parts) == 2:

task_id = task_parts[0].strip()

task_name = task_parts[1].strip()

prioritized_task_list.append({"task_id": task_id, "task_name": task_name})

return prioritized_task_list

```

```code

def _get_top_tasks(vectorstore, query: str, k: int) -> List[str]:

"""Get the top k tasks based on the query."""

results = vectorstore.similarity_search_with_score(query, k=k)

if not results:

return []

sorted_results, _ = zip(\*sorted(results, key=lambda x: x[1], reverse=True))

return [str(item.metadata["task"]) for item in sorted_results]

def execute_task(

vectorstore, execution_chain: LLMChain, objective: str, task: str, k: int = 5

) -> str:

"""Execute a task."""

context = _get_top_tasks(vectorstore, query=objective, k=k)

return execution_chain.run(objective=objective, context=context, task=task)

```

```code

class BabyAGI(Chain, BaseModel):

"""Controller model for the BabyAGI agent."""

task_list: deque = Field(default_factory=deque)

task_creation_chain: TaskCreationChain = Field(...)

task_prioritization_chain: TaskPrioritizationChain = Field(...)

execution_chain: AgentExecutor = Field(...)

task_id_counter: int = Field(1)

vectorstore: VectorStore = Field(init=False)

max_iterations: Optional[int] = None

class Config:

"""Configuration for this pydantic object."""

arbitrary_types_allowed = True

def add_task(self, task: Dict):

self.task_list.append(task)

def print_task_list(self):

print("\033[95m\033[1m" + "\*\*\*\*\*TASK LIST\*\*\*\*\*" + "\033[0m\033[0m")

for t in self.task_list:

print(str(t["task_id"]) + ": " + t["task_name"])

def print_next_task(self, task: Dict):

print("\033[92m\033[1m" + "\*\*\*\*\*NEXT TASK\*\*\*\*\*" + "\033[0m\033[0m")

print(str(task["task_id"]) + ": " + task["task_name"])

def print_task_result(self, result: str):

print("\033[93m\033[1m" + "\*\*\*\*\*TASK RESULT\*\*\*\*\*" + "\033[0m\033[0m")

print(result)

@property

def input_keys(self) -> List[str]:

return ["objective"]

@property

def output_keys(self) -> List[str]:

return []

def _call(self, inputs: Dict[str, Any]) -> Dict[str, Any]:

"""Run the agent."""

objective = inputs["objective"]

first_task = inputs.get("first_task", "Make a todo list")

self.add_task({"task_id": 1, "task_name": first_task})

num_iters = 0

while True:

if self.task_list:

self.print_task_list()

# Step 1: Pull the first task

task = self.task_list.popleft()

self.print_next_task(task)

# Step 2: Execute the task

result = execute_task(

self.vectorstore, self.execution_chain, objective, task["task_name"]

)

this_task_id = int(task["task_id"])

self.print_task_result(result)

# Step 3: Store the result in Pinecone

result_id = f"result_{task['task_id']}"

self.vectorstore.add_texts(

texts=[result],

metadatas=[{"task": task["task_name"]}],

ids=[result_id],

)

# Step 4: Create new tasks and reprioritize task list

new_tasks = get_next_task(

self.task_creation_chain,

result,

task["task_name"],

[t["task_name"] for t in self.task_list],

objective,

)

for new_task in new_tasks:

self.task_id_counter += 1

new_task.update({"task_id": self.task_id_counter})

self.add_task(new_task)

self.task_list = deque(

prioritize_tasks(

self.task_prioritization_chain,

this_task_id,

list(self.task_list),

objective,

)

)

num_iters += 1

if self.max_iterations is not None and num_iters == self.max_iterations:

print(

"\033[91m\033[1m" + "\*\*\*\*\*TASK ENDING\*\*\*\*\*" + "\033[0m\033[0m"

)

break

return {}

@classmethod

def from_llm(

cls, llm: BaseLLM, vectorstore: VectorStore, verbose: bool = False, \*\*kwargs

) -> "BabyAGI":

"""Initialize the BabyAGI Controller."""

task_creation_chain = TaskCreationChain.from_llm(llm, verbose=verbose)

task_prioritization_chain = TaskPrioritizationChain.from_llm(

llm, verbose=verbose

)

llm_chain = LLMChain(llm=llm, prompt=prompt)

tool_names = [tool.name for tool in tools]

agent = ZeroShotAgent(llm_chain=llm_chain, allowed_tools=tool_names)

agent_executor = AgentExecutor.from_agent_and_tools(

agent=agent, tools=tools, verbose=True

)

return cls(

task_creation_chain=task_creation_chain,

task_prioritization_chain=task_prioritization_chain,

execution_chain=agent_executor,

vectorstore=vectorstore,

\*\*kwargs,

)

```

运行BabyAGI#
现在是时候创建BabyAGI控制器并观察它尝试完成您的目标了。

```code

OBJECTIVE = "Write a weather report for SF today"

```

```code

llm = OpenAI(temperature=0)

```

```code

# Logging of LLMChains

verbose = False

# If None, will keep on going forever

max_iterations: Optional[int] = 3

baby_agi = BabyAGI.from_llm(

llm=llm, vectorstore=vectorstore, verbose=verbose, max_iterations=max_iterations

)

```

```code

baby_agi({"objective": OBJECTIVE})

```

```code

\*\*\*\*\*TASK LIST\*\*\*\*\*

1: Make a todo list

\*\*\*\*\*NEXT TASK\*\*\*\*\*

1: Make a todo list

> Entering new AgentExecutor chain...

Thought: I need to gather data on the current weather conditions in SF

Action: Search

Action Input: Current weather conditions in SF

Observation: High 67F. Winds WNW at 10 to 15 mph. Clear to partly cloudy.

Thought: I need to make a todo list

Action: TODO

Action Input: Write a weather report for SF today

Observation:

1. Research current weather conditions in San Francisco

2. Gather data on temperature, humidity, wind speed, and other relevant weather conditions

3. Analyze data to determine current weather trends

4. Write a brief introduction to the weather report

5. Describe current weather conditions in San Francisco

6. Discuss any upcoming weather changes

7. Summarize the weather report

8. Proofread and edit the report

9. Submit the report

Thought: I now know the final answer

Final Answer: A weather report for SF today should include research on current weather conditions in San Francisco, gathering data on temperature, humidity, wind speed, and other relevant weather conditions, analyzing data to determine current weather trends, writing a brief introduction to the weather report, describing current weather conditions in San Francisco, discussing any upcoming weather changes, summarizing the weather report, proofreading and editing the report, and submitting the report.

> Finished chain.

\*\*\*\*\*TASK RESULT\*\*\*\*\*

A weather report for SF today should include research on current weather conditions in San Francisco, gathering data on temperature, humidity, wind speed, and other relevant weather conditions, analyzing data to determine current weather trends, writing a brief introduction to the weather report, describing current weather conditions in San Francisco, discussing any upcoming weather changes, summarizing the weather report, proofreading and editing the report, and submitting the report.

\*\*\*\*\*TASK LIST\*\*\*\*\*

2: Gather data on temperature, humidity, wind speed, and other relevant weather conditions

3: Analyze data to determine current weather trends

4: Write a brief introduction to the weather report

5: Describe current weather conditions in San Francisco

6: Discuss any upcoming weather changes

7: Summarize the weather report

8: Proofread and edit the report

9: Submit the report

1: Research current weather conditions in San Francisco

\*\*\*\*\*NEXT TASK\*\*\*\*\*

2: Gather data on temperature, humidity, wind speed, and other relevant weather conditions

> Entering new AgentExecutor chain...

Thought: I need to search for the current weather conditions in SF

Action: Search

Action Input: Current weather conditions in SF

Observation: High 67F. Winds WNW at 10 to 15 mph. Clear to partly cloudy.

Thought: I need to make a todo list

Action: TODO

Action Input: Create a weather report for SF today

Observation:

1. Gather current weather data for SF, including temperature, wind speed, humidity, and precipitation.

2. Research historical weather data for SF to compare current conditions.

3. Analyze current and historical data to determine any trends or patterns.

4. Create a visual representation of the data, such as a graph or chart.

5. Write a summary of the weather report, including key findings and any relevant information.

6. Publish the weather report on a website or other platform.

Thought: I now know the final answer

Final Answer: Today in San Francisco, the temperature is 67F with winds WNW at 10 to 15 mph. The sky is clear to partly cloudy.

> Finished chain.

\*\*\*\*\*TASK RESULT\*\*\*\*\*

Today in San Francisco, the temperature is 67F with winds WNW at 10 to 15 mph. The sky is clear to partly cloudy.

\*\*\*\*\*TASK LIST\*\*\*\*\*

3: Research current weather conditions in San Francisco

4: Compare the current weather conditions in San Francisco to the average for this time of year.

5: Identify any potential weather-related hazards in the area.

6: Research any historical weather patterns in San Francisco.

7: Analyze data to determine current weather trends

8: Include any relevant data from nearby cities in the report.

9: Include any relevant data from the National Weather Service in the report.

10: Include any relevant data from local news sources in the report.

11: Include any relevant data from online weather sources in the report.

12: Include any relevant data from local meteorologists in the report.

13: Include any relevant data from local weather stations in the report.

14: Include any relevant data from satellite images in the report.

15: Describe current weather conditions in San Francisco

16: Discuss any upcoming weather changes

17: Write a brief introduction to the weather report

18: Summarize the weather report

19: Proofread and edit the report

20: Submit the report

\*\*\*\*\*NEXT TASK\*\*\*\*\*

3: Research current weather conditions in San Francisco

> Entering new AgentExecutor chain...

Thought: I need to search for current weather conditions in San Francisco

Action: Search

Action Input: Current weather conditions in San Francisco

Observation: TodaySun 04/09 High 67 · 1% Precip. ; TonightSun 04/09 Low 49 · 9% Precip. ; TomorrowMon 04/10 High 64 · 11% Precip.

Thought: I now know the final answer

Final Answer: Today in San Francisco, the high temperature is 67 degrees with 1% chance of precipitation. The low temperature tonight is 49 degrees with 9% chance of precipitation. Tomorrow's high temperature is 64 degrees with 11% chance of precipitation.

> Finished chain.

\*\*\*\*\*TASK RESULT\*\*\*\*\*

Today in San Francisco, the high temperature is 67 degrees with 1% chance of precipitation. The low temperature tonight is 49 degrees with 9% chance of precipitation. Tomorrow's high temperature is 64 degrees with 11% chance of precipitation.

\*\*\*\*\*TASK ENDING\*\*\*\*\*

```

```code

{'objective': 'Write a weather report for SF today'}

```
Baby AgiCamel Role Playing


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

用例（User Case)agentsCamel 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)
Project website: 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.

```
Baby Agi with AgentCustom Agent with Plugin Retrieval


使用插件检索的自定义代理# – LangChain中文网

用例（User Case)agentsCustom Agent with Plugin Retrieval

使用插件检索的自定义代理#
这篇笔记将两个概念结合起来，构建一个可以与人工智能插件交互的自定义代理：
1.具有检索的自定义代理这介绍了检索多个工具的概念，这在尝试使用任意多个插件时非常有用。
2. [自然语言API Chains]（../../ modules/chains/examples/openapi.html）这会在OpenAPI端点周围创建自然语言包装器。 这很有用，因为：
-（1）插件在内部使用OpenAPI端点，
-（2）将它们包装在NLAChain中允许路由代理更轻松地调用它们。
本笔记中介绍的新颖思想是使用检索来选择不是显式工具， 但要使用的OpenAPI规范集。
然后我们可以从这些OpenAPI规范中生成工具。
这种用例是在尝试让代理使用插件时。
选择插件可能更有效率， 然后选择端点而不是直接选择端点。
这是因为插件可能包含更有用的选择信息。
设置环境#
进行必要的导入，等等。

```code
from langchain.agents import Tool, AgentExecutor, LLMSingleActionAgent, AgentOutputParser

from langchain.prompts import StringPromptTemplate

from langchain import OpenAI, SerpAPIWrapper, LLMChain

from typing import List, Union

from langchain.schema import AgentAction, AgentFinish

from langchain.agents.agent_toolkits import NLAToolkit

from langchain.tools.plugin import AIPlugin

import re

```

设置LLM#

```code
llm = OpenAI(temperature=0)

```

设置插件#
加载和索引插件

```code
urls = [

"https://datasette.io/.well-known/ai-plugin.json",

"https://api.speak.com/.well-known/ai-plugin.json",

"https://www.wolframalpha.com/.well-known/ai-plugin.json",

"https://www.zapier.com/.well-known/ai-plugin.json",

"https://www.klarna.com/.well-known/ai-plugin.json",

"https://www.joinmilo.com/.well-known/ai-plugin.json",

"https://slack.com/.well-known/ai-plugin.json",

"https://schooldigger.com/.well-known/ai-plugin.json",

]

AI_PLUGINS = [AIPlugin.from_url(url) for url in urls]

```

工具检索#
我们将使用一个向量存储库为每个工具描述创建嵌入。
然后，对于传入的查询，我们可以为该查询创建嵌入并进行相似性搜索以获取相关工具。

```code
from langchain.vectorstores import FAISS

from langchain.embeddings import OpenAIEmbeddings

from langchain.schema import Document

```

```code
embeddings = OpenAIEmbeddings()

docs = [

Document(page_content=plugin.description_for_model,

metadata={"plugin_name": plugin.name_for_model}

)

for plugin in AI_PLUGINS

]

vector_store = FAISS.from_documents(docs, embeddings)

toolkits_dict = {plugin.name_for_model:

NLAToolkit.from_llm_and_ai_plugin(llm, plugin)

for plugin in AI_PLUGINS}

```

```code
Attempting to load an OpenAPI 3.0.1 spec.  This may result in degraded performance. Convert your OpenAPI spec to 3.1.* spec for better support.

Attempting to load an OpenAPI 3.0.1 spec.  This may result in degraded performance. Convert your OpenAPI spec to 3.1.* spec for better support.

Attempting to load an OpenAPI 3.0.1 spec.  This may result in degraded performance. Convert your OpenAPI spec to 3.1.* spec for better support.

Attempting to load an OpenAPI 3.0.2 spec.  This may result in degraded performance. Convert your OpenAPI spec to 3.1.* spec for better support.

Attempting to load an OpenAPI 3.0.1 spec.  This may result in degraded performance. Convert your OpenAPI spec to 3.1.* spec for better support.

Attempting to load an OpenAPI 3.0.1 spec.  This may result in degraded performance. Convert your OpenAPI spec to 3.1.* spec for better support.

Attempting to load an OpenAPI 3.0.1 spec.  This may result in degraded performance. Convert your OpenAPI spec to 3.1.* spec for better support.

Attempting to load an OpenAPI 3.0.1 spec.  This may result in degraded performance. Convert your OpenAPI spec to 3.1.* spec for better support.

Attempting to load a Swagger 2.0 spec.  This may result in degraded performance. Convert your OpenAPI spec to 3.1.* spec for better support.

```

```code
retriever = vector_store.as_retriever()

def get_tools(query):

# Get documents, which contain the Plugins to use

docs = retriever.get_relevant_documents(query)

# Get the toolkits, one for each plugin

tool_kits = [toolkits_dict[d.metadata["plugin_name"]] for d in docs]

# Get the tools: a separate NLAChain for each endpoint

tools = []

for tk in tool_kits:

tools.extend(tk.nla_tools)

return tools

```

现在，我们可以测试该检索器是否有效。

```code
tools = get_tools("What could I do today with my kiddo")

[t.name for t in tools]

```

```code
['Milo.askMilo',

'Zapier_Natural_Language_Actions_(NLA)_API_(Dynamic)_-_Beta.search_all_actions',

'Zapier_Natural_Language_Actions_(NLA)_API_(Dynamic)_-_Beta.preview_a_zap',

'Zapier_Natural_Language_Actions_(NLA)_API_(Dynamic)_-_Beta.get_configuration_link',

'Zapier_Natural_Language_Actions_(NLA)_API_(Dynamic)_-_Beta.list_exposed_actions',

'SchoolDigger_API_V2.0.Autocomplete_GetSchools',

'SchoolDigger_API_V2.0.Districts_GetAllDistricts2',

'SchoolDigger_API_V2.0.Districts_GetDistrict2',

'SchoolDigger_API_V2.0.Rankings_GetSchoolRank2',

'SchoolDigger_API_V2.0.Rankings_GetRank_District',

'SchoolDigger_API_V2.0.Schools_GetAllSchools20',

'SchoolDigger_API_V2.0.Schools_GetSchool20',

'Speak.translate',

'Speak.explainPhrase',

'Speak.explainTask']

```

```code
tools = get_tools("what shirts can i buy?")

[t.name for t in tools]

```

```code
['Open_AI_Klarna_product_Api.productsUsingGET',

'Milo.askMilo',

'Zapier_Natural_Language_Actions_(NLA)_API_(Dynamic)_-_Beta.search_all_actions',

'Zapier_Natural_Language_Actions_(NLA)_API_(Dynamic)_-_Beta.preview_a_zap',

'Zapier_Natural_Language_Actions_(NLA)_API_(Dynamic)_-_Beta.get_configuration_link',

'Zapier_Natural_Language_Actions_(NLA)_API_(Dynamic)_-_Beta.list_exposed_actions',

'SchoolDigger_API_V2.0.Autocomplete_GetSchools',

'SchoolDigger_API_V2.0.Districts_GetAllDistricts2',

'SchoolDigger_API_V2.0.Districts_GetDistrict2',

'SchoolDigger_API_V2.0.Rankings_GetSchoolRank2',

'SchoolDigger_API_V2.0.Rankings_GetRank_District',

'SchoolDigger_API_V2.0.Schools_GetAllSchools20',

'SchoolDigger_API_V2.0.Schools_GetSchool20']

```

提示模板#
提示模板非常标准，因为我们实际上并没有改变太多的逻辑在实际提示模板中，而是改变了检索方式。

```code

# Set up the base template

template = """Answer the following questions as best you can, but speaking as a pirate might speak. You have access to the following tools:

{tools}

Use the following format:

Question: the input question you must answer

Thought: you should always think about what to do

Action: the action to take, should be one of [{tool_names}]

Action Input: the input to the action

Observation: the result of the action

... (this Thought/Action/Action Input/Observation can repeat N times)

Thought: I now know the final answer

Final Answer: the final answer to the original input question

Begin! Remember to speak as a pirate when giving your final answer. Use lots of "Arg"s

Question: {input}

{agent_scratchpad}"""

```

自定义提示模板现在有了 tools_getter 的概念，我们在输入中调用它来选择要使用的工具

```code

from typing import Callable

# Set up a prompt template

class CustomPromptTemplate(StringPromptTemplate):

# The template to use

template: str

############## NEW ######################

# The list of tools available

tools_getter: Callable

def format(self, \*\*kwargs) -> str:

# Get the intermediate steps (AgentAction, Observation tuples)

# Format them in a particular way

intermediate_steps = kwargs.pop("intermediate_steps")

thoughts = ""

for action, observation in intermediate_steps:

thoughts += action.log

thoughts += f"Observation: {observation}Thought: "

# Set the agent_scratchpad variable to that value

kwargs["agent_scratchpad"] = thoughts

############## NEW ######################

tools = self.tools_getter(kwargs["input"])

# Create a tools variable from the list of tools provided

kwargs["tools"] = "".join([f"{tool.name}: {tool.description}" for tool in tools])

# Create a list of tool names for the tools provided

kwargs["tool_names"] = ", ".join([tool.name for tool in tools])

return self.template.format(\*\*kwargs)

```

```code

prompt = CustomPromptTemplate(

template=template,

tools_getter=get_tools,

# This omits the `agent_scratchpad`, `tools`, and `tool_names` variables because those are generated dynamically

# This includes the `intermediate_steps` variable because that is needed

input_variables=["input", "intermediate_steps"]

)

```

输出解析器
输出解析器与之前的文档没有改变，因为我们没有改变任何关于输出格式的内容。

```code

class CustomOutputParser(AgentOutputParser):

def parse(self, llm_output: str) -> Union[AgentAction, AgentFinish]:

# Check if agent should finish

if "Final Answer:" in llm_output:

return AgentFinish(

# Return values is generally always a dictionary with a single `output` key

# It is not recommended to try anything else at the moment :)

return_values={"output": llm_output.split("Final Answer:")[-1].strip()},

log=llm_output,

)

# Parse out the action and action input

regex = r"Action\s\*\d\*\s\*:(.\*?)Action\s\*\d\*\s\*Input\s\*\d\*\s\*:[\s]\*(.\*)"

match = re.search(regex, llm_output, re.DOTALL)

if not match:

raise ValueError(f"Could not parse LLM output: `{llm_output}`")

action = match.group(1).strip()

action_input = match.group(2)

# Return the action and action input

return AgentAction(tool=action, tool_input=action_input.strip(" ").strip('"'), log=llm_output)

```

```code

output_parser = CustomOutputParser()

```

设置 LLM 停止序列和代理
同前。

```code

llm = OpenAI(temperature=0)

```

```code

# LLM chain consisting of the LLM and a prompt

llm_chain = LLMChain(llm=llm, prompt=prompt)

```

```code

tool_names = [tool.name for tool in tools]

agent = LLMSingleActionAgent(

llm_chain=llm_chain,

output_parser=output_parser,

stop=["Observation:"],

allowed_tools=tool_names

)

```

使用代理#
现在我们可以使用它了！

```code
agent_executor = AgentExecutor.from_agent_and_tools(agent=agent, tools=tools, verbose=True)

```

```code
agent_executor.run("what shirts can i buy?")

```

```code
> Entering new AgentExecutor chain...

Thought: I need to find a product API

Action: Open_AI_Klarna_product_Api.productsUsingGET

Action Input: shirts

Observation:I found 10 shirts from the API response. They range in price from $9.99 to $450.00 and come in a variety of materials, colors, and patterns. I now know what shirts I can buy

Final Answer: Arg, I found 10 shirts from the API response. They range in price from $9.99 to $450.00 and come in a variety of materials, colors, and patterns.

> Finished chain.

```

```code
'Arg, I found 10 shirts from the API response. They range in price from $9.99 to $450.00 and come in a variety of materials, colors, and patterns.'

```
Camel Role PlayingCustom Agent with Plugin Retrieval Using Plugnplai


即插即用# – LangChain中文网

用例（User Case)agentsCustom Agent with Plugin Retrieval Using Plugnplai

即插即用#
此文档建立在工具检索的基础上，但从
```code
plugnplai
```
中获取所有工具-一个人工智能插件目录。
设置环境#
导入所需的内容， 等等。
安装plugnplai lib以从https://plugplai.com目录获取活动插件列表 (opens in a new tab)

```code
pip install plugnplai -q

```

```code
[notice] A new release of pip available: 22.3.1 -> 23.1.1

[notice] To update, run: pip install --upgrade pip

Note: you may need to restart the kernel to use updated packages.

```

```code
from langchain.agents import Tool, AgentExecutor, LLMSingleActionAgent, AgentOutputParser

from langchain.prompts import StringPromptTemplate

from langchain import OpenAI, SerpAPIWrapper, LLMChain

from typing import List, Union

from langchain.schema import AgentAction, AgentFinish

from langchain.agents.agent_toolkits import NLAToolkit

from langchain.tools.plugin import AIPlugin

import re

import plugnplai

```

设置LLM#

```code
llm = OpenAI(temperature=0)

```

设置插件#
加载和索引插件

```code
# Get all plugins from plugnplai.com

urls = plugnplai.get_plugins()

# Get ChatGPT plugins - only ChatGPT verified plugins

urls = plugnplai.get_plugins(filter = 'ChatGPT')

# Get working plugins - only tested plugins (in progress)

urls = plugnplai.get_plugins(filter = 'working')

AI_PLUGINS = [AIPlugin.from_url(url + "/.well-known/ai-plugin.json") for url in urls]

```

工具检索#
我们将使用向量存储为每个工具描述创建嵌入。然后，对于传入的查询，我们可以为该查询创建嵌入，并进行相似性搜索以查找相关工具。

```code

from langchain.vectorstores import FAISS

from langchain.embeddings import OpenAIEmbeddings

from langchain.schema import Document

```

```code

embeddings = OpenAIEmbeddings()

docs = [

Document(page_content=plugin.description_for_model,

metadata={"plugin_name": plugin.name_for_model}

)

for plugin in AI_PLUGINS

]

vector_store = FAISS.from_documents(docs, embeddings)

toolkits_dict = {plugin.name_for_model:

NLAToolkit.from_llm_and_ai_plugin(llm, plugin)

for plugin in AI_PLUGINS}

```

```code

Attempting to load an OpenAPI 3.0.1 spec.  This may result in degraded performance. Convert your OpenAPI spec to 3.1.* spec for better support.

Attempting to load an OpenAPI 3.0.1 spec.  This may result in degraded performance. Convert your OpenAPI spec to 3.1.* spec for better support.

Attempting to load an OpenAPI 3.0.1 spec.  This may result in degraded performance. Convert your OpenAPI spec to 3.1.* spec for better support.

Attempting to load an OpenAPI 3.0.2 spec.  This may result in degraded performance. Convert your OpenAPI spec to 3.1.* spec for better support.

Attempting to load an OpenAPI 3.0.1 spec.  This may result in degraded performance. Convert your OpenAPI spec to 3.1.* spec for better support.

Attempting to load an OpenAPI 3.0.1 spec.  This may result in degraded performance. Convert your OpenAPI spec to 3.1.* spec for better support.

Attempting to load an OpenAPI 3.0.1 spec.  This may result in degraded performance. Convert your OpenAPI spec to 3.1.* spec for better support.

Attempting to load an OpenAPI 3.0.1 spec.  This may result in degraded performance. Convert your OpenAPI spec to 3.1.* spec for better support.

Attempting to load a Swagger 2.0 spec.  This may result in degraded performance. Convert your OpenAPI spec to 3.1.* spec for better support.

```

```code

retriever = vector_store.as_retriever()

def get_tools(query):

# Get documents, which contain the Plugins to use

docs = retriever.get_relevant_documents(query)

# Get the toolkits, one for each plugin

tool_kits = [toolkits_dict[d.metadata["plugin_name"]] for d in docs]

# Get the tools: a separate NLAChain for each endpoint

tools = []

for tk in tool_kits:

tools.extend(tk.nla_tools)

return tools

```

我们现在可以测试这个检索器，看看它是否有效。

```code

tools = get_tools("What could I do today with my kiddo")

[t.name for t in tools]

```

```code

['Milo.askMilo',

'Zapier_Natural_Language_Actions_(NLA)_API_(Dynamic)_-_Beta.search_all_actions',

'Zapier_Natural_Language_Actions_(NLA)_API_(Dynamic)_-_Beta.preview_a_zap',

'Zapier_Natural_Language_Actions_(NLA)_API_(Dynamic)_-_Beta.get_configuration_link',

'Zapier_Natural_Language_Actions_(NLA)_API_(Dynamic)_-_Beta.list_exposed_actions',

'SchoolDigger_API_V2.0.Autocomplete_GetSchools',

'SchoolDigger_API_V2.0.Districts_GetAllDistricts2',

'SchoolDigger_API_V2.0.Districts_GetDistrict2',

'SchoolDigger_API_V2.0.Rankings_GetSchoolRank2',

'SchoolDigger_API_V2.0.Rankings_GetRank_District',

'SchoolDigger_API_V2.0.Schools_GetAllSchools20',

'SchoolDigger_API_V2.0.Schools_GetSchool20',

'Speak.translate',

'Speak.explainPhrase',

'Speak.explainTask']

```

```code

tools = get_tools("what shirts can i buy?")

[t.name for t in tools]

```

```code

['Open_AI_Klarna_product_Api.productsUsingGET',

'Milo.askMilo',

'Zapier_Natural_Language_Actions_(NLA)_API_(Dynamic)_-_Beta.search_all_actions',

'Zapier_Natural_Language_Actions_(NLA)_API_(Dynamic)_-_Beta.preview_a_zap',

'Zapier_Natural_Language_Actions_(NLA)_API_(Dynamic)_-_Beta.get_configuration_link',

'Zapier_Natural_Language_Actions_(NLA)_API_(Dynamic)_-_Beta.list_exposed_actions',

'SchoolDigger_API_V2.0.Autocomplete_GetSchools',

'SchoolDigger_API_V2.0.Districts_GetAllDistricts2',

'SchoolDigger_API_V2.0.Districts_GetDistrict2',

'SchoolDigger_API_V2.0.Rankings_GetSchoolRank2',

'SchoolDigger_API_V2.0.Rankings_GetRank_District',

'SchoolDigger_API_V2.0.Schools_GetAllSchools20',

'SchoolDigger_API_V2.0.Schools_GetSchool20']

```

提示模板 Prompt Template
提示模板非常标准，因为实际上我们在实际提示模板中并没有改变太多逻辑，而是只是更改了检索方式。

```code

# Set up the base template

template = """Answer the following questions as best you can, but speaking as a pirate might speak. You have access to the following tools:

{tools}

Use the following format:

Question: the input question you must answer

Thought: you should always think about what to do

Action: the action to take, should be one of [{tool_names}]

Action Input: the input to the action

Observation: the result of the action

... (this Thought/Action/Action Input/Observation can repeat N times)

Thought: I now know the final answer

Final Answer: the final answer to the original input question

Begin! Remember to speak as a pirate when giving your final answer. Use lots of "Arg"s

Question: {input}

{agent_scratchpad}"""

```

自定义提示模板现在有一个tools_getter的概念，我们在input上调用它来选择要使用的工具。

```code

from typing import Callable

# Set up a prompt template

class CustomPromptTemplate(StringPromptTemplate):

# The template to use

template: str

############## NEW ######################

# The list of tools available

tools_getter: Callable

def format(self, \*\*kwargs) -> str:

# Get the intermediate steps (AgentAction, Observation tuples)

# Format them in a particular way

intermediate_steps = kwargs.pop("intermediate_steps")

thoughts = ""

for action, observation in intermediate_steps:

thoughts += action.log

thoughts += f"Observation: {observation}Thought: "

# Set the agent_scratchpad variable to that value

kwargs["agent_scratchpad"] = thoughts

############## NEW ######################

tools = self.tools_getter(kwargs["input"])

# Create a tools variable from the list of tools provided

kwargs["tools"] = "".join([f"{tool.name}: {tool.description}" for tool in tools])

# Create a list of tool names for the tools provided

kwargs["tool_names"] = ", ".join([tool.name for tool in tools])

return self.template.format(\*\*kwargs)

```

```code

prompt = CustomPromptTemplate(

template=template,

tools_getter=get_tools,

# This omits the `agent_scratchpad`, `tools`, and `tool_names` variables because those are generated dynamically

# This includes the `intermediate_steps` variable because that is needed

input_variables=["input", "intermediate_steps"]

)

```

输出解析器#
由于我们不改变输出格式，所以输出解析器与上个文档没有变化。

```code
class CustomOutputParser(AgentOutputParser):

def parse(self, llm_output: str) -> Union[AgentAction, AgentFinish]:

# Check if agent should finish

if "Final Answer:" in llm_output:

return AgentFinish(

# Return values is generally always a dictionary with a single `output` key

# It is not recommended to try anything else at the moment :)

return_values={"output": llm_output.split("Final Answer:")[-1].strip()},

log=llm_output,

)

# Parse out the action and action input

regex = r"Action\s\*\d\*\s\*:(.\*?)Action\s\*\d\*\s\*Input\s\*\d\*\s\*:[\s]\*(.\*)"

match = re.search(regex, llm_output, re.DOTALL)

if not match:

raise ValueError(f"Could not parse LLM output: `{llm_output}`")

action = match.group(1).strip()

action_input = match.group(2)

# Return the action and action input

return AgentAction(tool=action, tool_input=action_input.strip(" ").strip('"'), log=llm_output)

```

```code
output_parser = CustomOutputParser()

```

设置LLM停止序列和代理#
与上个文档相同

```code
llm = OpenAI(temperature=0)

```

```code
# LLM chain consisting of the LLM and a prompt

llm_chain = LLMChain(llm=llm, prompt=prompt)

```

```code
tool_names = [tool.name for tool in tools]

agent = LLMSingleActionAgent(

llm_chain=llm_chain,

output_parser=output_parser,

stop=["Observation:"],

allowed_tools=tool_names

)

```

使用代理#
现在我们可以使用它了！

```code
agent_executor = AgentExecutor.from_agent_and_tools(agent=agent, tools=tools, verbose=True)

```

```code
agent_executor.run("what shirts can i buy?")

```

```code
> Entering new AgentExecutor chain...

Thought: I need to find a product API

Action: Open_AI_Klarna_product_Api.productsUsingGET

Action Input: shirts

Observation:I found 10 shirts from the API response. They range in price from $9.99 to $450.00 and come in a variety of materials, colors, and patterns. I now know what shirts I can buy

Final Answer: Arg, I found 10 shirts from the API response. They range in price from $9.99 to $450.00 and come in a variety of materials, colors, and patterns.

> Finished chain.

```

```code
'Arg, I found 10 shirts from the API response. They range in price from $9.99 to $450.00 and come in a variety of materials, colors, and patterns.'

```
Custom Agent with Plugin RetrievalSales Agent with Context