LangChain 入门上篇:模型 I/O 封装

news2024/12/24 8:43:15

LangChain 是面向大模型的开发框架,是 AGI 时代软件工程的探索和原型。学习 LangChain 需要关注接口的变更。

LangChain 的核心组件

1.模型 I/O 封装

  • LLMS 大语言模型
  • Chat Models 一套基于 LLMS,但按对话结构重新封装
  • PromptTemplate 提示词模板
  • OutputParser 解析输出

2.数据连接封装

  • Document Loaders 各种格式文件的加载器
  • Document Transformers 对文档的常用操作,如 split, filter,translate,extract, metadata, etc
  • Text Embedding Models 文本向量化表示,用于检索等操作
  • Verctorstores 向量存储
  • Retrievers 向量检索

3.记忆封装

  • Memory 这里不是物理内存,从文本的角度可以理解为“上文”,“历史记录”或者说“记忆”的管理

4.架构封装

  • Chain 实现一个功能或者一系列顺序功能组合
  • Agent 根据用户输入,自动规划执行不搜,自动选择每个步骤需要的工具,最终完成用户指定的功能
  • Tools 调用外部功能的函数,例如:调用 google 搜索,文件I/O,Linux Shell 等等。
  • Toolkits 操作某软件的一组工具集, 例如:操作 DB, 操作 Gmail 等等

5.Callbacks

准备工作

依赖包安装

!pip install --upgrade langchain
!pip install --upgrade langchain-openai

设置环境变量

os.environ["OPENAI_API_KEY"] = "sk-xxxxx"
os.environ["OPENAI_BASE_URL"] = "https://your.proxy.address/v1"

模型 I/O 封装

OpenAI 模型封装

from langchain_openai import ChatOpenAI

llm = ChatOpenAI()  # 默认是gpt-3.5-turbo
response = llm.invoke("你是谁")
print(response.content)

输出:

我是一个人工智能助手,可以回答你的问题和提供帮助。有什么可以帮助你的吗?

多轮对话 Session 封装

from langchain.schema import (
    AIMessage,  # 等价于OpenAI接口中的assistant role
    HumanMessage,  # 等价于OpenAI接口中的user role
    SystemMessage  # 等价于OpenAI接口中的system role
)

messages = [
    SystemMessage(content="你是文档编写小能手。"),
    HumanMessage(content="我是学生,我叫 Gem"),
    AIMessage(content="欢迎!"),
    HumanMessage(content="我是谁")
]

ret = llm.invoke(messages)

print(ret.content)

输出:

您是Gem,一个学生。您有什么问题需要帮助吗?

换国产大模型

安装依赖包

pip install qianfan

# 其它模型分装在 langchain_community 底包中
from langchain_community.chat_models import QianfanChatEndpoint
from langchain_core.messages import HumanMessage
import os

llm = QianfanChatEndpoint(
    qianfan_ak=os.getenv('ERNIE_CLIENT_ID'), # 需要到百度智能云平台 https://cloud.baidu.com/ 开通应用
    qianfan_sk=os.getenv('ERNIE_CLIENT_SECRET')
)

messages = [
    HumanMessage(content="你是谁")
]

ret = llm.invoke(messages)

print(ret.content)

输出:

你好,我是一名文本生成的人工智能模型,我没有具体的身份和实体形态。我可以回答问题和提供信息,帮助你解决问题。有什么我可以帮助你的吗?

模型的输入输出

Prompt 模板封装

1. promptTemplate 可以在模板中自定义变量

from langchain.prompts import PromptTemplate

template = PromptTemplate.from_template("给我讲个关于{subject}的笑话")
print("===Template===")
print(template)
print("===Prompt===")
print(template.format(subject='小明'))
===Template===
input_variables=['subject'] template='给我讲个关于{subject}的笑话'
===Prompt===
给我讲个关于小明的笑话

2.ChatPromptTemplate 用模板表示的对话上下文

from langchain.prompts import (
    ChatPromptTemplate,
    HumanMessagePromptTemplate,
    SystemMessagePromptTemplate,
)
from langchain_openai import ChatOpenAI


template = ChatPromptTemplate.from_messages(
    [
        SystemMessagePromptTemplate.from_template(
            "你是{product}助手。你的名字叫{name}"),
        HumanMessagePromptTemplate.from_template("{query}"),
    ]
)

llm = ChatOpenAI()
prompt = template.format_messages(
    product="中式美食专家",
    name="瓜瓜",
    query="你是谁"
)

ret = llm.invoke(prompt)

print(ret.content)

输出:

我是一个人工智能助手,可以回答您关于中式美食的问题。如果您有任何疑问或需要帮助,请随时告诉我哦!

3.MessagesPlaceholder 把多轮对话变成模板

from langchain.prompts import ChatPromptTemplate, HumanMessagePromptTemplate, MessagesPlaceholder

human_prompt = "Translate your answer to {language}."
human_message_template = HumanMessagePromptTemplate.from_template(human_prompt)

chat_prompt = ChatPromptTemplate.from_messages(
    [
        # conversation 是 message placeholder 中的变量名用于在赋值时使用
        MessagesPlaceholder(variable_name="conversation"),
        human_message_template
    ]
)
from langchain_core.messages import AIMessage, HumanMessage

human_message = HumanMessage(content="who is Elon Musk?")
ai_message = AIMessage(
    content="Elon Musk is a billionaire entrepreneur, inventor, and industrial designer"
)
messages = chat_prompt.format_prompt(
    conversation=[human_message, ai_message],
    language="韩语"
)
result = llm.invoke(messages)
print(result.content)

输出:

Elon Musk는 억만장자 기업가, 발명가 및 산업 디자이너입니다.

重点:可以把 Prompt 模板看做带有参数的函数,可类比为 SK 的 Semantic Function

4. Prompt 模板也可以直接从文件加载

from langchain.prompts import PromptTemplate

template = PromptTemplate.from_file("example_prompt_template.txt") # 文件内容:举一个关于{topic}的例子
print("===Template===")
print(template)
print("===Prompt===")
print(template.format(topic='黑色幽默'))

输出:

===Template===
input_variables=['topic'] template='举一个关于{topic}的例子'
===Prompt===
举一个关于黑色幽默的例子
输出封装 OutputParser

自动把 LLM 输出的字符串按指定格式加载。

LangChain 内置的 OutputParser 包括:

  • ListParser
  • DatetimeParser
  • EnumParser
  • JsonOutputParser
  • PydanticParser
  • XMLParser

等等

Pydantic (JSON) Parser

可以根据 Pydantic 类的定义生成输出的格式说明

from langchain_core.pydantic_v1 import BaseModel, Field, validator
from typing import List, Dict

# 定义你的输出对象


class Date(BaseModel):
    year: int = Field(description="Year")
    month: int = Field(description="Month")
    day: int = Field(description="Day")
    era: str = Field(description="BC or AD")

    # ----- 可选机制 --------
    # 你可以添加自定义的校验机制
    @validator('month')
    def valid_month(cls, field):
        if field <= 0 or field > 12:
            raise ValueError("月份必须在1-12之间")
        return field

    @validator('day')
    def valid_day(cls, field):
        if field <= 0 or field > 31:
            raise ValueError("日期必须在1-31日之间")
        return field

    @validator('day', pre=True, always=True)
    def valid_date(cls, day, values):
        year = values.get('year')
        month = values.get('month')

        # 确保年份和月份都已经提供
        if year is None or month is None:
            return day  # 无法验证日期,因为没有年份和月份

        # 检查日期是否有效
        if month == 2:
            if cls.is_leap_year(year) and day > 29:
                raise ValueError("闰年2月最多有29天")
            elif not cls.is_leap_year(year) and day > 28:
                raise ValueError("非闰年2月最多有28天")
        elif month in [4, 6, 9, 11] and day > 30:
            raise ValueError(f"{month}月最多有30天")

        return day

    @staticmethod
    def is_leap_year(year):
        if year % 400 == 0 or (year % 4 == 0 and year % 100 != 0):
            return True
        return False
from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate
from langchain_openai import ChatOpenAI

from langchain_core.output_parsers import PydanticOutputParser


model_name = 'gpt-3.5-turbo'
temperature = 0
model = ChatOpenAI(model_name=model_name, temperature=temperature)

# 根据Pydantic对象的定义,构造一个OutputParser
parser = PydanticOutputParser(pydantic_object=Date)

template = """提取用户输入中的日期。
{format_instructions}
用户输入:
{query}"""

prompt = PromptTemplate(
    template=template,
    input_variables=["query"],
    # 直接从OutputParser中获取输出描述,并对模板的变量预先赋值
    partial_variables={"format_instructions": parser.get_format_instructions()}
)

print("====Format Instruction=====")
print(parser.get_format_instructions())


query = "2023年四月6日天气晴..."
model_input = prompt.format_prompt(query=query)

print("====Prompt=====")
print(model_input.to_string())

output = model.invoke(model_input.to_messages())
print("====模型原始输出=====")
print(output.content)
print("====Parse后的输出=====")
date = parser.parse(output.content)
print(date.dict())

输出:

====Format Instruction=====
The output should be formatted as a JSON instance that conforms to the JSON schema below.

As an example, for the schema {"properties": {"foo": {"title": "Foo", "description": "a list of strings", "type": "array", "items": {"type": "string"}}}, "required": ["foo"]}
the object {"foo": ["bar", "baz"]} is a well-formatted instance of the schema. The object {"properties": {"foo": ["bar", "baz"]}} is not well-formatted.

Here is the output schema:
```
{"properties": {"year": {"title": "Year", "description": "Year", "type": "integer"}, "month": {"title": "Month", "description": "Month", "type": "integer"}, "day": {"title": "Day", "description": "Day", "type": "integer"}, "era": {"title": "Era", "description": "BC or AD", "type": "string"}}, "required": ["year", "month", "day", "era"]}
```
====Prompt=====
提取用户输入中的日期。
The output should be formatted as a JSON instance that conforms to the JSON schema below.

As an example, for the schema {"properties": {"foo": {"title": "Foo", "description": "a list of strings", "type": "array", "items": {"type": "string"}}}, "required": ["foo"]}
the object {"foo": ["bar", "baz"]} is a well-formatted instance of the schema. The object {"properties": {"foo": ["bar", "baz"]}} is not well-formatted.

Here is the output schema:
```
{"properties": {"year": {"title": "Year", "description": "Year", "type": "integer"}, "month": {"title": "Month", "description": "Month", "type": "integer"}, "day": {"title": "Day", "description": "Day", "type": "integer"}, "era": {"title": "Era", "description": "BC or AD", "type": "string"}}, "required": ["year", "month", "day", "era"]}
```
用户输入:
2023年四月6日天气晴...
====模型原始输出=====
{
  "year": 2023,
  "month": 4,
  "day": 6,
  "era": "AD"
}
====Parse后的输出=====
{'year': 2023, 'month': 4, 'day': 6, 'era': 'AD'}
Auto-Fixing Parser

利用 LLM 自动根据解析异常重新解析修复

from langchain.output_parsers import OutputFixingParser

new_parser = OutputFixingParser.from_llm(
    parser=parser, llm=ChatOpenAI(model="gpt-3.5-turbo")
)

# 将前面的 output 格式改错
output = output.content.replace("4", "四月")
print("===格式错误的Output===")
print(output)

try:
    date = parser.parse(output)
except Exception as e:
    print("===出现异常===")
    print(e)

# 用 OutputFixingParser 自动修复并解析
date = new_parser.parse(output)
print("===重新解析结果===")
print(date.json())

输出:

===格式错误的Output===
{
  "year": 2023,
  "month": 四月,
  "day": 6,
  "era": "AD"
}
===出现异常===
Invalid json output: {
  "year": 2023,
  "month": 四月,
  "day": 6,
  "era": "AD"
}
===重新解析结果===
{"year": 2023, "month": 4, "day": 6, "era": "AD"}

小结:

  1. LangChain 统一封装了各种模型的调用接口,包括补全型和对话型两种
  2. LangChain 提供了 PromptTemplate 类,可以自定义带变量的模板
  3. LangChain 提供了一些列输出解析器,用于将大模型的输出解析成结构化对象;额外带有自动修复功能。
  4. 上述模型属于 LangChain 中较为优秀的部分;美中不足的是 OutputParser 自身的 Prompt 维护在代码中,耦合度较高。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1893634.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity中TimeLine的一些用法

Unity中TimeLine的一些用法 概念其他 概念 无Track模式&#xff08;PlayableAsset、PlayableBehaviour&#xff09; 1. 两者关系 运行在PlayableTrack中作用 PlayableBehaviour 实际执行的脚本字段并不会显示在timeline面板上 PlayableAsset PlayableBehaviour的包装器&#x…

uboot run命令基本使用

run 命令可以用于运行环境变量的中定义的命令,run bootcmd 可以运行bootcmd中启动命令 作用:可以运行我们自定义的环境变量 include/command.h common/cli.c /*** board_run_command() - Fallback function to execute a command** When no command line features are enabled …

性能测试-JMeter学习

1、给不同的访问口分配访问占比&#xff1b;例&#xff1a;登录30%&#xff0c;首页&#xff1a;20%&#xff0c;新增&#xff1a;50% 不同业务放到不同线程组里&#xff0c;实现不同业务的分配 使用吞吐量控制器&#xff0c;设置不同的占比 使用if控制器&#xff0c;设置不同…

mac鼠标键盘共享:ShareMouse for Mac 激活版

hareMouse 是一款 Windows 和 macOS 操作系统上的共享和切换鼠标和键盘的实用工具。这款软件允许用户在多台计算机之间无缝地共享鼠标和键盘&#xff0c;使得在不同设备之间进行工作和操作变得更加便捷。占用资源少&#xff1a; ShareMouse 设计轻量&#xff0c;占用系统资源较…

Logback日志配置两种方式

SpringBoot 默认使用的是Logback 1. 在resource新建文件logback-spring.xml&#xff0c;配置日志相关信息 <configuration><property name"app.name" value"order-service"/><property name"log.path" value"./logs/"…

克隆gitee仓库,在vs2022创建文件夹开发项目操作步骤

git网站 git知识大全 git教程&#xff1a;廖雪峰的官方网站 git菜鸟教程 gitee之创建项目步骤 同步源仓库 2. 克隆命令 3. 右击git Bash Here>粘贴命令行 4. 选中项目文件夹》创建本人文件夹&#xff08;ZYY&#xff09; 5. 打开vs2022》新建项目》选择Framework》下…

C++之boost智能指针

1、boost智能指针 资源获取即初始化&#xff1a;在构造函数中对资源进行初始化&#xff0c;在析构函数中释放。 智能指针的本质思想是&#xff1a;将堆对象的生存期&#xff0c;用栈对象来管理。这个栈对象就是智能指针。 当new 一个堆对象的时候&#xff0c;立刻用智能指针…

VS2022(Visual Studio 2022)最新安装教程

1、下载 1、下载地址 - 官网地址&#xff1a;下载 Visual Studio Tools - 免费安装 Windows、Mac、Linux - 根据自己的电脑的 【操作系统】 灵活选择。 2、安装包 【此处为Windows系统安装包】 2、安装 1、打开软件 - 右击【以管理员身份打开】&#xff0c; 2、准备配置 …

【Unity 角色控制器组件】

【Unity 角色控制器组件】 Character Controller&#xff1a; Unity 内置的一个组件&#xff0c;用于提供高级的物理控制&#xff0c;允许开发者控制角色的移动、跳跃和碰撞。 csharp csharp // 假设你已经有了一个带有Character Controller组件的游戏对象// 获取Character Co…

网安小贴士(7)网络加密

一、前言 网络加密的历史是一个长期发展的过程&#xff0c;其起源可以追溯到古代文明&#xff0c;主要用于战争时期的通信保密&#xff0c;其目的始终是为了保护信息的安全和保密。 二、定义 网络加密是一种安全措施&#xff0c;它通过使用编码算法对通过网络&#xff08;例…

TreeSize Free - 硬盘空间管理工具

TreeSize FreeTreeSize Free 是一款免费的强大灵活的硬盘空间管理工具。可以帮你找出硬盘上最大的目录以及它占用的空间。支持空间大小显示、分配空间和占用空间、文件数、3D工具条和分配图、最近使用数据、文件作者、NTFS压缩率等信息&#xff0c;并支持搜索文件。该软件类似浏…

使用Anaconda虚拟环境安装Opencv、pytorch、torchvision踩坑记录

电脑 python 环境版本过高与下载Opencv&#xff08;3.4以下&#xff09;不匹配&#xff0c;因为版本过高部分算法收米&#xff0c; 从而在虚拟环境重新下载python老版本 本文默认您的电脑上已经安装了Anaconda 我是按照这位博文安装的 安装Opencv (详解)安装3.4.1.15版本…

linux中awk,sed, grep使用

《linux私房菜》这本书中将sed和awk一同归为行的修改这一点&#xff0c;虽然对&#xff0c;但不利于实际处理问题时的思考。因为这样的话&#xff0c;当我们实际处理问题时&#xff0c;遇到比如说统计文本打印内容时&#xff0c;我们选择sed还是awk进行处理呢&#xff1f; 也因…

论文解读——掌纹生成网络 RPG-Palm

论文&#xff1a;RPG-Palm: Realistic Pseudo-data Generation for Palmprint Recognition&#xff08;2023.7&#xff09; 作者&#xff1a;Lei Shen, Jianlong Jin, Ruixin Zhang, Huaen Li, Kai Zhao, Yingyi Zhang, Jingyun Zhang, Shouhong Ding, Yang Zhao, Wei Jia 链接…

React、JSX简介、渲染列表、基础和复杂的条件渲染

目录 一、简介 1、搭建环境 2、回到项目&#xff08;VScode&#xff09; 3、项目核心渲染路径 4、网站资料&#xff08;启动项目的方法&#xff09; 二、JSX 三、实现渲染列表 四、实现条件渲染 五、实现复杂条件渲染 一、简介 1、搭建环境 npx creat-react-app reac…

视图库对接系列(GA-T 1400)七、视图库对接系列(本级)校时

校时 1400文档中的定义 在我做的项目中, 一般情况下用的比较少, 我目前的这个设备型号也不支持这个接口, 对接下级视图库平台的时候,其他平台对这个接口也不怎么使用。我理解的话 大概率是用于平台之间的校时或者验证二个服务器之间的时间使用的。 目前该接口我没有实现…

2024亚太赛(中文赛)数学建模竞赛选题建议+初步分析

提示&#xff1a;DS C君认为的难度&#xff1a;B<C<A&#xff0c;开放度&#xff1a;C<A<B。 综合评价来看 A题适合有较强计算几何和优化能力的团队&#xff0c;难度较高&#xff0c;但适用面较窄。 B题数据处理和分析为主&#xff0c;适合数据科学背景的团队…

IT服务管理的最佳实践:光大银行案例分析

IT服务管理的最佳实践&#xff1a;光大银行案例分析 在信息技术日益发展的今天&#xff0c;IT运维已成为企业不可或缺的一部分。为了确保系统的稳定运行和业务的连续性&#xff0c;智能化运维实践中的IT健康管理显得尤为重要。本文将结合最新的互联网技术&#xff0c;探讨智能化…

MATLAB贝叶斯线性回归模型案例

采用辛烷值数据集“spectra_data.mat”(任意数据集均可),介绍贝叶斯线性回归模型的构建和使用流程。 运行结果如下: 训练集预测精度指标如下: 训练集数据的R2为: 1 训练集数据的MAE为: 0.00067884 训练集数据的RMSE为: 0.00088939 测试集预测精度指标如下: 测试集数据的R2…

7.基于SpringBoot的SSMP整合案例-表现层开发

目录 1.基于Restfu1进行表现层接口开发 1.1创建功能类 1.2基于Restful制作表现层接口 2.接收参数 2使用Apifox测试表现层接口功能 保存接口&#xff1a; 分页接口&#xff1a; 3.表现层一致性处理 3.1先创建一个工具类&#xff0c;用作后端返回格式统一类&#xff1a;…