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

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.mfbz.cn/a/770300.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

七、函数练习

目录 1. 写一个函数可以判断一个数是不是素数。&#xff08;素数只能被1或其本身整除的数&#xff09; 2. 一个函数判断一年是不是闰年。 3.写一个函数&#xff0c;实现一个整形有序数组的二分查找。 4. 写一个函数&#xff0c;每调用一次这个函数&#xff0c;使得num每次增…

Appium+python自动化(三十九)-Appium自动化测试框架综合实践 - 代码实现(超详解)

1.简介 今天我们紧接着上一篇继续分享Appium自动化测试框架综合实践 - 代码实现。由于时间的关系&#xff0c;宏哥这里用代码给小伙伴演示两个模块&#xff1a;注册和登录。 2.业务模块封装 因为现在各种APP的层出不群&#xff0c;各式各样的。但是其大多数都有注册、登录。为…

【话题】IT专业入门,高考假期预习指南

IT专业入门&#xff0c;高考假期预习指南 亲爱的高考学子们&#xff0c; 七月的阳光&#xff0c;如同你们的梦想&#xff0c;炽热而明亮。当你们手中的笔落下最后一道题的答案&#xff0c;那不仅仅是对过去十二年寒窗苦读的告别&#xff0c;更是对未知世界探索的启程号角。你们…

surfer做等值线图笔记

surfer等值线图及其白化 **grd文件的制作****白化的边界文件的制作****白化****绘图****逆转坐标轴** grd文件的制作 单击格网&#xff0c;选择x,y,z的数据&#xff0c;选择克里金插值方法&#xff0c;让后确定&#xff0c;保存grd文件 白化的边界文件的制作 surfer新建表&am…

拒绝胶感,清纯甜美邻家女孩!逼真!逼真!SD1.5 更适合初恋般的国产真人大模型—— CNrealisticMIXV40

看惯了AI艺术大片&#xff0c;想寻找适合生成邻家女孩青涩照片的模型。 今天应邀&#xff0c;针对邻家女孩青涩风格进行下尝试。此前推荐过一款支持各种真实&#xff0c;摄影&#xff0c;写实风格模型的合体模型——**赛博Dream | CNrealistic_MIX_V40无损修剪版。**这款模型为…

notepad++ 中文乱码 出现小方格

从word文档直接拷贝过来的文字&#xff0c;到notepad 中文乱码 出现小方格 &#xff1a; 方法&#xff1a;设置-语言格式设置&#xff0c;字体样式更改为宋体&#xff0c;勾选“使用全局字体”&#xff0c;点保存并关闭&#xff0c;则ok

【Python机器学习】算法链与管道——用预处理进行参数选择的注意项

对于许多机器学习算法&#xff0c;提供的特定数据表示非常重要。比如&#xff0c;首先对数据进行缩放&#xff0c;然后手动合并特征&#xff0c;再利用无监督机器学习来学习特征。因此&#xff0c;大多数机器学习应用不仅需要应用多个算法&#xff0c;而且还需要将许多不同的处…

使用 llamaIndex 快速实现智能体

AI 智能体就是可以根据当前环境进行推理&#xff0c;并根据处理结果进行下一步的操作。简单来说 AI 智能体可以与外界环境进行交互&#xff0c;并根据结果执行更复杂的操作。本文将通过llamaIndex 实现一个简单的 Agent 实时获取数据&#xff0c;由于大模型是通过静态数据进行训…

【C++】 解决 C++ 语言报错:未定义行为(Undefined Behavior)

文章目录 引言 未定义行为&#xff08;Undefined Behavior, UB&#xff09;是 C 编程中非常危险且难以调试的错误之一。未定义行为发生时&#xff0c;程序可能表现出不可预测的行为&#xff0c;导致程序崩溃、安全漏洞甚至硬件损坏。本文将深入探讨未定义行为的成因、检测方法…

ERROR TypeError: AutoImport is not a function TypeError: AutoImport is not a

出现这种错误是AutoImport is not a function&#xff08;插件版本问题&#xff0c;回退插件版本&#xff09;-vue项目element plus按需引入配置错误 查看unplugin-auto 插件版本 npm list unplugin-auto-import 回退插件版本 npm install unplugin-auto-import0.16.1 ERRO…

字符串相似度算法完全指南:编辑、令牌与序列三类算法的全面解析与深入分析

在自然语言处理领域&#xff0c;人们经常需要比较字符串&#xff0c;这些字符串可能是单词、句子、段落甚至是整个文档。如何快速判断两个单词或句子是否相似&#xff0c;或者相似度是好还是差。这类似于我们使用手机打错一个词&#xff0c;但手机会建议正确的词来修正它&#…

无法定位程序输入点…于动态链接库…的解决方法

如下图所示: 出现上述问题,主要是因为使用的动态库问题,具体就是电脑里有几个不同版本的osgEarth的动态库。如下图所示,本人电脑里编译了好几个版本的osgEarth库,并且把其中的两个加入到了环境变量中,导致出现上述错误: 程序使用的是绿框所示的D:\OSGCore\OSGEarth\bin …

哈喽GPT-4o,对GPT-4o 论文速写的思考与探索

作为一款强大的语言模型&#xff0c;ChatGPT 在论文写作上具备显著优势。它能够辅助学者或研究人员自动创建论文框架、摘要、文献综述及论文段落&#xff08;如引言、方法、结果、结论等&#xff09;。此外&#xff0c;ChatGPT 还能优化论文结构、润色、降低内容重复率&#xf…

redis-cluster(集群模式搭建)

redis中间件版本: redis-5.0.5环境介绍 这里使用服务器数量3&#xff0c;分别为172.0.0.1&#xff0c;172.0.0.2&#xff0c;172.0.0.3&#xff0c;每台机器redis节点数量2个&#xff0c;共6个redis节点构成redis-cluster模式。编译安装包 在172.0.0.1的机器上进入安装目录 cd …

AI大模型从入门到精通:一站式学习教程

前言 在聊到AI的时候&#xff0c;我们都离不开“大模型”这三个字。 AI大模型已经完全融入了各个领域&#xff0c;也融入了我们的生活&#xff0c;它好像无所不在、无所不能。 百度李彦宏说 &#xff1a;大模型改变世界&#xff1b; 360周鸿祎说&#xff1a;大模型是新时代“…

Frida案例-hook app中指定类的方法

界面如下 代码如下 点击‘点赞’按钮时&#xff0c;会触发getThumbsCount&#xff08;&#xff09;函数 当前期望能通过frida获取getThumbsCount&#xff08;&#xff09;的值 首先查看手机上正在运行的进程 frida-ps -U 进程不一定会以包名显示&#xff0c;还可能会以app的名…

基于主流SpringBoot进行JavaWeb开发的学习路线

目录 一、学习路线 &#xff08;1&#xff09;第一部分&#xff08;Web前端开发的技术栈&#xff09; &#xff08;2&#xff09;第二部分&#xff08;Web后端开发&#xff09; 二、学习之后必备的技能 三、学习Web开发的基础与未来的收获 学完这一类知识目标&#xff1a;…

vxe-table的序号一样

使用vxe-table的时候&#xff0c;有的时候会出现序号相同的现象&#xff0c;这种现象一般出现在我们后面自己添加的行中&#xff0c;就像这种 此时的这三个序号是相同的&#xff0c;我来说一下原因&#xff0c;这是在添加新的一行的时候&#xff0c;有的时候数据很多&#xff0…

理解MySQL核心技术:外键(Foreign Key)的设计与实现

在日常开发中&#xff0c;数据库是必不可少的部分&#xff0c;而MySQL作为最流行的关系型数据库之一&#xff0c;广泛应用于各类项目中。为了确保数据的完整性和一致性&#xff0c;外键&#xff08;Foreign Key&#xff09;无疑是一个重要的概念。在本篇文章中&#xff0c;我们…

认识100种电路之降压电路

在电子电路的世界里&#xff0c;降压电路扮演着至关重要的角色。 【为什么电路需要降压电路】 首先&#xff0c;我们要明白&#xff0c;不同的电子设备和元件往往需要特定的电压来正常工作。比如&#xff0c;某些芯片可能需要 5V 的电压&#xff0c;而我们提供的电源可能是 12…