# 入门指南


本教程将为您快速介绍如何使用LangChain构建端到端的语言模型应用程序。

## 安装

请使用以下命令安装LangChain：

```bash
pip install langchain
# or
conda install langchain -c conda-forge
```


## 环境设置

通常使用LangChain需要将其与一个或多个模型提供者、数据存储、API等进行集成。

在本示例中，我们将使用OpenAI的API，因此我们首先需要安装其SDK：


```bash
pip install openai
```

接下来我们需要在终端中设置环境变量。

```bash
export OPENAI_API_KEY="..."
```

是的，没错。您可以在 Jupyter 笔记本或 Python 脚本中设置环境变量。以下是设置环境变量的代码示例：

```python
import os
os.environ["OPENAI_API_KEY"] = "..."
```


## 构建语言模型应用程序：LLMs

现在我们已经安装了 LangChain 并设置好了环境，可以开始构建我们的语言模型应用程序了。

LangChain 提供了许多模块，可以用来构建语言模型应用程序。这些模块可以组合使用，创建更复杂的应用程序，或者单独用于简单的应用程序。



`````{dropdown} LLMs: 从语言模型获取预测结果

LangChain 最基本的构建块是在某些输入上调用 LLM。让我们通过一个简单的示例来演示如何实现这一点。为此，假设我们正在构建一个服务，根据公司的产品生成公司名称。

为了实现这一点，我们首先需要导入 LLM 包，例如OpenAI。

```python
from langchain.llms import OpenAI
```

接下来，我们可以使用任何参数来初始化LLM。在这个例子中，我们希望输出结果更随机一些，因此我们将使用较高的temperature（这也是OpenAI的API参数，温度代表了分子平均随机运动的快慢，因此借用温度来表示随机性）值来初始化。

```python
llm = OpenAI(temperature=0.9)
```

现在我们可以调用它了！

```python
text = "请用中文给生产彩色袜子的公司起个好名字。"
print(llm(text))
```

```pycon
色活靓履
```

有关如何在 LangChain 中使用 LLMs 的更多详细信息，请参见 [LLM 入门指南](../modules/models/llms/getting_started.ipynb).
`````


`````{dropdown} Prompt Templates (提示模板): 为语言模型管理提示

调用 LLM 是我们开始的第一步。但通常在应用中使用 LLM 时，您不会直接将用户输入发送到 LLM 中。您可能会按照业务场景需要，简化用户的输入。然后按适合当前场景的模式，对输入进行修饰和调整后再发送到 LLM 中。

例如，在先前的示例中，我们传递的文本是硬编码以要求为制造彩色袜子的公司命名。在这个想象中的服务中，我们希望做的是只获取描述公司的用户输入，然后使用这些信息格式化提示。

这在 LangChain 中非常容易！

首先，让我们定义提示模板：

```python
from langchain.prompts import PromptTemplate

prompt = PromptTemplate(
    input_variables=["product"],
    template="请用中文给生产{product}的公司起个好名字",
)
```

现在让我们看看它的工作原理！我们可以调用 .format 方法来格式化它。

```python
print(prompt.format(product="彩色袜子"))
```

```pycon
请用中文给生产彩色袜子的公司起个好名字
```


[想要了解更多详细信息，请参阅提示模板的入门指南。](../modules/prompts/chat_prompt_template.ipynb)

`````



`````{dropdown} Chains（链）：在多步流程中将 LLM（语言模型）和 Prompt Templates （提示模板）结合起来。

到目前为止，我们已经单独使用了 PromptTemplate 和 LLM 这些基础组件。他们不仅可以单独使用，还可以“链接”在一起组合使用。

在 LangChain 中，“链”由“链接”组成，“链接”可以是像 LLM 这样的基础组件或其他链。

例如：LLMChain 就是最核心的“链”类型，由 PromptTemplate 和 LLM 组成。

扩展之前的例子，我们可以构造一个 LLMChain，它接受用户输入，使用 PromptTemplate 进行格式化，并将格式化的响应传递给 LLM。

```python
from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI

llm = OpenAI(temperature=0.9)
prompt = PromptTemplate(
    input_variables=["product"],
    template="请用中文给生产{product}的公司起个好名字",
)
```

现在我们可以创建一个非常简单的链，该链将接受用户输入，然后用 PromptTemplate（提示模版）进行格式化，最后将其发送给 LLM（语言模型）：

```python
from langchain.chains import LLMChain
chain = LLMChain(llm=llm, prompt=prompt)
```

现在我们可以运行该链，只需指定产品即可获得我们期望的结果！

```python
chain.run("彩色袜子")
# -> '\n\n彩色星足!'
```

第一个链成功执行了！ - 一个 LLM 链。虽然这只是一种较简单的链，但理解它的工作原理会为您使用更复杂的链打下良好的基础。

[要了解更多详情，请查看链的入门指南。](../modules/chains/getting_started.ipynb)

`````


`````{dropdown} Agents(代理)：根据用户输入动态调用链

到目前为止，我们所讨论的链都是按照预定顺序运行的。

而代理不再是这样：它们使用 LLM 确定要采取的操作以及其顺序。一个操作可以是使用工具并观察其输出，或将结果返回给用户。

如果使用得当，代理可以非常强大。在本教程中，我们将通过最简单的、最高级别的 API，向您展示如何轻松地使用代理。

为了加载代理，您应该理解以下概念：

- 工具: 执行特定任务的函数。这可以是诸如 Google 搜索、数据库查找、Python REPL、其他链之类的工具。目前工具的接口是一个期望输入为字符串并输出字符串的函数。
- LLM: 驱动代理的语言模型。注意：这里指代理通过语言模型自己判断选择使用哪些工具
- 代理: 通过引用代理类的名字字符串，指定要使用的代理。本篇介绍专注于最简单的、最高级别的 API，所以仅涵盖使用标准支持的代理类。如果要实现自定义代理，请参阅自定义代理的文档（即将推出）。

**代理**: 有关支持的代理及其规格列表，请参考 [here](../modules/agents/agents.md).

**工具**: 有关预定义工具及其规格列表，请参见 [here](../modules/agents/tools.md).

接下来这个例子需要安装 SerpAPI Python 包。

```bash
pip install google-search-results
```

然后设置环境变量。

```python
import os
os.environ["SERPAPI_API_KEY"] = "..."
```

现在我们可以开始了！

```python
from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType
from langchain.llms import OpenAI

# 首先，让我们加载我们将用来控制代理的语言模型。
llm = OpenAI(temperature=0)

# 接下来，让我们加载一些要使用的工具。请注意，“llm-math”工具使用LLM，因此我们需要传递LLM。
tools = load_tools(["serpapi", "llm-math"], llm=llm)

# 最后，让我们使用这些工具、语言模型和我们想要使用的代理类型来初始化一个代理。
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)

# 现在让我们来测试一下吧！
agent.run("What was the high temperature in SF yesterday in Fahrenheit? What is that number raised to the .023 power?")
```

```pycon
> Entering new AgentExecutor chain...
 I need to find the temperature first, then use the calculator to raise it to the .023 power.
Action: Search
Action Input: "High temperature in SF yesterday"
Observation: San Francisco Temperature Yesterday. Maximum temperature yesterday: 57 °F (at 1:56 pm) Minimum temperature yesterday: 49 °F (at 1:56 am) Average temperature ...
Thought: I now have the temperature, so I can use the calculator to raise it to the .023 power.
Action: Calculator
Action Input: 57^.023
Observation: Answer: 1.0974509573251117

Thought: I now know the final answer
Final Answer: The high temperature in SF yesterday in Fahrenheit raised to the .023 power is 1.0974509573251117.

> Finished chain.
```


`````


`````{dropdown} Memory(记忆)：将状态添加到链和代理中。

到目前为止，我们所讨论的所有链和代理都是无状态的。但通常情况下，您可能希望链或代理具有某种“记忆”概念，以便它可以记住有关其先前交互的信息。这种情况最清晰和简单的例子是设计聊天机器人 - 您希望它记住以前的消息，以便它可以利用上下文进行更好的对话。这将是一种“短期记忆”。在更复杂的方面，您可以想象链/代理随着时间的推移记住关键信息 - 这将是一种“长期记忆”。有关后者的更具体的想法，请参见 [论文](https://memprompt.com/).

LangChain 提供了几个专门为此目的创建的链。本笔记本演示了使用其中一条链（ConversationChain）和两种不同类型的记忆的方法。

默认情况下，ConversationChain 具有一种简单的记忆类型，它记住了所有先前的输入/输出，并将它们添加到传递的上下文中。让我们看一下如何使用这个链（将verbose=True，以便我们可以看到提示）。

```python
from langchain import OpenAI, ConversationChain

llm = OpenAI(temperature=0)
conversation = ConversationChain(llm=llm, verbose=True)

conversation.predict(input="Hi there!")
```

```pycon
> Entering new chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.

Current conversation:

Human: Hi there!
AI:

> Finished chain.
' Hello! How are you today?'
```

```python
conversation.predict(input="I'm doing well! Just having a conversation with an AI.")
```

```pycon
> Entering new chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.

Current conversation:

Human: Hi there!
AI:  Hello! How are you today?
Human: I'm doing well! Just having a conversation with an AI.
AI:

> Finished chain.
" That's great! What would you like to talk about?"
```
`````

## 构建语言模型类应用程序：聊天模型

同样地，您可以使用聊天模型而不是 LLM。聊天模型是语言模型的一种变体。虽然聊天模型在底层使用语言模型，但它们公开的界面有点不同：它们不是公开一个“文本输入，文本输出”的 API，而是公开一个“聊天信息”是输入和输出的接口。

聊天模型 API 还比较新，因此我们仍在摸索正确的抽象化方法。


`````{dropdown} 在聊天模型中获取消
您可以通过向聊天模型传递一个或多个消息来获得聊天回复。响应将是一个消息。目前在 LangChain 中支持的消息类型有 AIMessage、HumanMessage、SystemMessage 和 ChatMessage，其中 ChatMessage 接受一个任意角色参数。大多数情况下，您只需要处理 HumanMessage、AIMessage 和 SystemMessage 即可

```python
from langchain.chat_models import ChatOpenAI
from langchain.schema import (
    AIMessage,
    HumanMessage,
    SystemMessage
)

chat = ChatOpenAI(temperature=0)
```

您可以通过传入单个消息来获取回复

```python
chat([HumanMessage(content="翻译句子从英文到中文. I love programming.")])
# -> AIMessage(content="我喜欢编程。", additional_kwargs={})
```

您还可以针对 OpenAI 的 GPT-3.5 Turbo 和 GPT-4 模型传入多个消息。

```python
messages = [
    SystemMessage(content="你是我的英文翻译中文助理"),
    HumanMessage(content="翻译句子从英文到中文. I love programming.")
]
chat(messages)
# -> AIMessage(content="我喜欢编程。", additional_kwargs={})
```

您可以进一步采用 "generate" 函数生成多组消息的完成度建议。这将返回一个带有额外 "message" 参数的 "LLMResult"。
```python
batch_messages = [
    [
        SystemMessage(content="你是我的英文翻译中文助理"),
        HumanMessage(content="翻译句子从英文到中文. I love programming.")
    ],
    [
        SystemMessage(content="你是我的英文翻译中文助理"),
        HumanMessage(content="翻译句子从英文到中文. I love artificial intelligence.")
    ],
]
result = chat.generate(batch_messages)
result
# -> LLMResult(generations=[[ChatGeneration(text='我喜欢编程。', generation_info=None, message=AIMessage(content='我喜欢编程。', additional_kwargs={}))], [ChatGeneration(text='我喜爱人工智能。', generation_info=None, message=AIMessage(content='我喜爱人工智能。', additional_kwargs={}))]], llm_output={'token_usage': {'prompt_tokens': 95, 'completion_tokens': 19, 'total_tokens': 114}, 'model_name': 'gpt-3.5-turbo'})
```

您可以从这个 "LLMResult" 中恢复令牌使用情况等信息。
```
result.llm_output['token_usage']
# -> {'prompt_tokens': 95, 'completion_tokens': 19, 'total_tokens': 114}
```
`````

`````{dropdown} Chat Prompt Templates（聊天提示模版）
类似于 LLM 模型，您可以使用 “MessagePromptTemplate” 模板来进行 templating。您可以构建一个 ChatPromptTemplate，从一个或多个 MessagePromptTemplate 构建。您可以使用 ChatPromptTemplate 的 format_prompt - 这将返回一个 PromptValue，您可以将其转换为字符串或 Message 对象，这取决于您是否想将格式化的值用作 llm 或 chat 模型的输入。

为了方便起见，模板上公开了一个 “from_template” 方法。如果您使用此模板，它会是这样的：

```python
from langchain.chat_models import ChatOpenAI
from langchain.prompts.chat import (
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
)

chat = ChatOpenAI(temperature=0)

template="You are a helpful assistant that translates {input_language} to {output_language}."
system_message_prompt = SystemMessagePromptTemplate.from_template(template)
human_template="{text}"
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)

chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])

# get a chat completion from the formatted messages
chat(chat_prompt.format_prompt(input_language="English", output_language="French", text="I love programming.").to_messages())
# -> AIMessage(content="J'aime programmer.", additional_kwargs={})
```
`````

`````{dropdown} 在Chain(链)中使用聊天模型
上面讨论的 LLMChain 也可以与聊天模型一起使用：

```python
from langchain.chat_models import ChatOpenAI
from langchain import LLMChain
from langchain.prompts.chat import (
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
)

chat = ChatOpenAI(temperature=0)

template="You are a helpful assistant that translates {input_language} to {output_language}."
system_message_prompt = SystemMessagePromptTemplate.from_template(template)
human_template="{text}"
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])

chain = LLMChain(llm=chat, prompt=chat_prompt)
chain.run(input_language="English", output_language="French", text="I love programming.")
# -> "J'aime programmer."
```
`````

`````{dropdown} 在Agents(代理)中使用聊天模型
也可以将代理与聊天模型一起使用，您可以使用 AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION 作为代理类型进行初始化。

```python
from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType
from langchain.chat_models import ChatOpenAI
from langchain.llms import OpenAI

# 首先，让我们加载我们将用来控制代理的语言模型。
chat = ChatOpenAI(temperature=0)

# 接下来，让我们加载一些工具来使用。请注意，llm-math 工具使用 LLM，因此我们需要将其传递给它。
llm = OpenAI(temperature=0)
tools = load_tools(["serpapi", "llm-math"], llm=llm)


# 最后，让我们使用这些工具、语言模型和我们想要使用的代理类型来初始化一个代理。
agent = initialize_agent(tools, chat, agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION, verbose=True)

# 现在让我们测试一下！
agent.run("Who is Olivia Wilde's boyfriend? What is his current age raised to the 0.23 power?")
```

```pycon

> Entering new AgentExecutor chain...
Thought: I need to use a search engine to find Olivia Wilde's boyfriend and a calculator to raise his age to the 0.23 power.
Action:
{
  "action": "Search",
  "action_input": "Olivia Wilde boyfriend"
}

Observation: Sudeikis and Wilde's relationship ended in November 2020. Wilde was publicly served with court documents regarding child custody while she was presenting Don't Worry Darling at CinemaCon 2022. In January 2021, Wilde began dating singer Harry Styles after meeting during the filming of Don't Worry Darling.
Thought:I need to use a search engine to find Harry Styles' current age.
Action:
{
  "action": "Search",
  "action_input": "Harry Styles age"
}

Observation: 29 years
Thought:Now I need to calculate 29 raised to the 0.23 power.
Action:
{
  "action": "Calculator",
  "action_input": "29^0.23"
}

Observation: Answer: 2.169459462491557

Thought:I now know the final answer.
Final Answer: 2.169459462491557

> Finished chain.
'2.169459462491557'
```
`````

`````{dropdown} Memory（记忆）: 为 Chain（链）与 Agents（代理）添加状态
可以在使用聊天模型初始化的链和代理中使用记忆。与针对语言模型的记忆不同的是，我们可以将之前的所有消息作为唯一的记忆对象保留，而不试图将其压缩为一个字符串。

```python
from langchain.prompts import (
    ChatPromptTemplate, 
    MessagesPlaceholder, 
    SystemMessagePromptTemplate, 
    HumanMessagePromptTemplate
)
from langchain.chains import ConversationChain
from langchain.chat_models import ChatOpenAI
from langchain.memory import ConversationBufferMemory

prompt = ChatPromptTemplate.from_messages([
    SystemMessagePromptTemplate.from_template("下面是人类和人工智能之间的友好对话。人工智能很健谈，提供了许多来自上下文的具体细节。如果人工智能不知道回答一个问题，它会诚实地说出自己不知道。"),
    MessagesPlaceholder(variable_name="history"),
    HumanMessagePromptTemplate.from_template("{input}")
])

llm = ChatOpenAI(temperature=0)
memory = ConversationBufferMemory(return_messages=True)
conversation = ConversationChain(memory=memory, prompt=prompt, llm=llm)

conversation.predict(input="Hi there!")
# -> 'Hello! How can I assist you today?'


conversation.predict(input="I'm doing well! Just having a conversation with an AI.")
# -> "That sounds like fun! I'm happy to chat with you. Is there anything specific you'd like to talk about?"

conversation.predict(input="Tell me about yourself.")
# -> "Sure! I am an AI language model created by OpenAI. I was trained on a large dataset of text from the internet, which allows me to understand and generate human-like language. I can answer questions, provide information, and even have conversations like this one. Is there anything else you'd like to know about me?"
```
`````
