在上一节LangChain-快速开启大模型开发之旅(介绍与安装)我们已经简单介绍过LangChain出现的行业背景和简洁的安装过程,下面就通过对三大组件的几个示例来快速学习如何上手。

模型 I/O

模型 I/O 包含三个部分:

  • 提示模板:使用固定格式的模板产生批量格式化输入,便于多次请求迭代调整数据
  • 模型选择:选择适合任务需求的模型并初始化,接收提示模板格式化后的数据作为输入,使用模型进行处理
  • 输出解析:隐式在prompt末尾加入输出格式的信息(例如json)使模型能够识别到输出格式的要求,从而产生结构化的数据,再使用解析器对输出数据进行处理,最终得到更加规整的信息

下面是一个完整的模型I/O的示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# 导入OpenAI Key
import os

# os.environ["OPENAI_API_KEY"] = '你的OpenAI API Key'

# 导入LangChain中的提示模板
from langchain.prompts import PromptTemplate

# 创建提示模板
prompt_template = """您是一位经验丰富的计算机专家。
对于售价为 {price} 元的 {gpu_name} ,您能提供一个吸引人的简短描述吗?
{format_instructions}"""

# 通过LangChain调用模型
from langchain_openai import OpenAI, ChatOpenAI

# 创建模型实例
# model = OpenAI(model_name='gpt-3.5-turbo-instruct')
model = ChatOpenAI(model=os.environ.get("LLM_MODELEND"))

# 导入结构化输出解析器和ResponseSchema
from langchain.output_parsers import StructuredOutputParser, ResponseSchema

# 定义我们想要接收的响应模式
response_schemas = [
ResponseSchema(name="description", description="显卡的描述文案"),
ResponseSchema(name="reason", description="问什么要这样写这个文案"),
]
# 创建输出解析器
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)

# 获取格式指示
format_instructions = output_parser.get_format_instructions()
# 根据模板创建提示,同时在提示中加入输出解析器的说明
prompt = PromptTemplate.from_template(
prompt_template, partial_variables={"format_instructions": format_instructions}
)

# 数据准备
gpus = ["MX150", "AMD RX580", "NVIDIA RTX 4090"]
prices = ["50", "300", "20000"]

# 创建一个空的DataFrame用于存储结果
import pandas as pd

df = pd.DataFrame(columns=["gpu", "price", "description", "reason"]) # 先声明列名

for gpu, price in zip(gpus, prices):
# 根据提示准备模型的输入
input = prompt.format(gpu_name=gpu, price=price)

# 获取模型的输出
output = model.invoke(input)
# 解析模型的输出(这是一个字典结构)
parsed_output = output_parser.parse(output.content)
print(parsed_output)

# 在解析后的输出中添加“gpu”和“price”
parsed_output["gpu"] = gpu
parsed_output["price"] = price

# 将解析后的输出添加到DataFrame中
df.loc[len(df)] = parsed_output


# 保存DataFrame到CSV文件
df.to_csv("gpus_with_descriptions.csv", index=False)

输出如下

{‘description’: ‘MX150 显卡,仅售 50 元!性能卓越,轻松应对各种图形处理任务,让你的电脑焕发新生!’, ‘reason’: ‘突出了显卡的低价和高性能,能够吸引消费者的注意力,同时强调了其在图形处理方面的能力,让用户对其性价比有更清晰的认识。’}
{‘description’: ‘AMD RX580 显卡,仅售 300 元!性能强劲,畅玩游戏无压力,高性价比之选!’, ‘reason’: ‘突出了显卡的价格优势和性能特点,能够吸引消费者的关注,同时强调了高性价比,让消费者更容易产生购买欲望。’}
{‘description’: ‘NVIDIA RTX 4090,售价 20000 元,极致性能的代表,带你畅享震撼游戏与专业创作体验。’, ‘reason’: ‘突出了显卡的高售价,同时强调其极致性能,能够吸引追求高性能的用户群体,让他们了解到该显卡在游戏和专业创作方面能带来出色的表现。’}

检索

数据检索常用来查询存储在本地的向量,下面就给出一个简单的向量检索器示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 设置OpenAI的API密钥
import os
os.environ["OPENAI_API_KEY"] = 'Your OpenAI Key'

# 导入文档加载器模块,并使用TextLoader来加载文本文件
from langchain.document_loaders import TextLoader
loader = TextLoader('LangChainSamples/OneFlower/手搓cpu秘籍.txt', encoding='utf8')

# 使用VectorstoreIndexCreator来从加载器创建索引
from langchain.indexes import VectorstoreIndexCreator
index = VectorstoreIndexCreator().from_loaders([loader])

# 定义查询字符串, 使用创建的索引执行查询
query = "ic设计中最关键的一步是什么?"
result = index.query(query)
print(result) # 打印查询结果

除了向量检索器以外,LangChain还有多查询检索器、上下文压缩检索器等等,他们都有相似的接口,可以根据需求查询相关文档进行调用

代理

前面介绍过,代理就是让模型能够调用外部工具从而实现更加强大的功能,那么让我们先调用ReAct框架让模型学会模仿人类思考行动的方式。 请注意,这里的ReAct并不是流行的前端框架React,而是指导大语言模型推理和行动的一种思维框架。ReAct的名称来源于推理(Reasoning)和行动(Acting)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 设置OpenAI和SERPAPI的API密钥
import os

os.environ["SERPAPI_API_KEY"] = (
"Your SERPAPI API KEY"
)
os.environ["OPENAI_API_KEY"] = (
"Your OpenAI API KEY"
)

# 加载所需的库
from langchain_community.agent_toolkits.load_tools import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType
from langchain_openai import ChatOpenAI # ChatOpenAI模型

# 初始化大模型
llm = ChatOpenAI(model=os.environ["LLM_MODELEND"], temperature=0)

# 设置工具
tools = load_tools(["serpapi", "llm-math"], llm=llm)

# 初始化Agent
agent = initialize_agent(
tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True
)

# 跑起来
agent.invoke(
"目前市场上显卡的平均价格是多少?如果我在此基础上加价15%卖出,应该如何定价?"
)

LangChain通过Agent类,将ReAct框架进行了完美封装和实现,使得调用接口极为简洁,我们只用了一般api调用的代码量就赋予了AI相当大的自主性(Autonomy)。