前言

前面几节课里,我带大家了解了Function Calling的基础用法以及LCEL的基本概念,那这节课我将带大家深入了解其进阶用法,结合 LangChain 框架,讲解如何实现文本标签提取(Tagging)与结构化信息抽取(Extraction)

相比于传统纯文本的问答方式,Function Calling 允许我们以更结构化、更可控的方式从大模型中获取精准数据,为智能系统提供更强的上下文感知能力。

无论你是初学者,还是有一定开发经验的技术爱好者,这篇教程都将用清晰的逻辑、丰富的实例帮助你快速掌握这项关键能力。


基础知识:什么是Function Calling?

Function Calling 是 OpenAI 模型的一项高级能力,允许模型不直接生成回答,而是返回一个函数调用请求(包含函数名与参数),由开发者决定是否执行,执行后再将结果反馈回模型以继续对话流程。

这种设计的优势在于:

  • 增强可控性:我们可以检查模型的函数调用意图,避免错误调用。

  • 提升灵活性:可以加入校验机制、格式转换等操作。

  • 支持结构化输入输出:便于和已有系统对接,如数据库、API等。

Function Calling 通常和 Pydantic、LangChain 等配套使用,能够以更易维护的方式快速构建复杂的交互逻辑。那下面就让我们开始实战看看其作用吧!


实战Part1:文本标注(Tagging)

我们从一个简单的文本标注任务开始:

给定一段文本,判断其情感(正面/负面/中性)以及语言(如英文en、中文zh等)。

定义数据模型

在这一步,我们借助 Pydantic 创建一个用于情感与语言标注的数据结构,并用 LangChain 提供的工具将其转换为大模型可识别的 function 调用格式。这样,模型便能“知道”有哪些字段需要填写。

from pydantic import BaseModel, Field
class Tagging(BaseModel):
    sentiment: str = Field(description="文本的情感倾向,取值为 `pos`(正面)、`neg`(负面)或 `neutral`(中性)")
    language: str = Field(description="文本所用语言(ISO 639-1 语言代码)")

转换为函数结构后,大模型将会返回一个 JSON 格式的结构化调用请求,而不是直接输出文本:

from langchain_core.utils.function_calling import convert_to_openai_function
convert_to_openai_function(Tagging)

构建对话链条

我们使用 LangChain 的 ChatPromptTemplate 构造提示词模板,同时绑定模型并明确指定调用的函数。这样可以保证模型不产生歧义,而是直接触发我们定义好的函数结构。在使用前我们可以需要先通过pip install -U langchain langchain-openai 安装一下openai的配套库。

from langchain.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
model = ChatOpenAI(
    model="qwen-turbo",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key="api_key"# 请替换成你的 API key
)

prompt = ChatPromptTemplate.from_messages([
    ("system", "请仔细思考并按照要求对文本进行标注"),
    ("user", "{input}")
])

model_with_functions = model.bind(
    functions=[convert_to_openai_function(Tagging)],
    function_call={"name": "Tagging"}
)

tagging_chain = prompt | model_with_functions

调用与解析结果

一切就绪后,我们调用该链条,并传入待标注的文本。模型会根据定义好的函数结构返回带有 sentiment 和 language 字段的结果:

print(tagging_chain.invoke({"input": "I love langchain"}))

输出结果如下:

content='' additional_kwargs={'function_call': {'arguments': '{"sentiment": "pos", "language": "en"}', 'name': 'Tagging'}} response_metadata={'token_usage': {'completion_tokens': 18, 'prompt_tokens': 241, 'total_tokens': 259, 'completion_tokens_details': None}, 'model_name': 'qwen-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-6f20d16d-94a0-4a58-89ce-a95a3c8ed7cb-0'

可以看到其Function Call里面的arguments识别出来的是积极(pos)的情绪,并且也写出对应的语言英文(en)。为了进一步规范输出,我们还可以追加一个解析器,使得输出内容更清爽:

from langchain.output_parsers.openai_functions import JsonOutputFunctionsParser
tagging_chain = prompt | model_with_functions | JsonOutputFunctionsParser()
print(tagging_chain.invoke({"input": "I love langchain"}))

这样模型就只会选择出Function Call部分的内容,输出结果如下:

{'sentiment': 'pos', 'language': 'en'}

实战Part2:信息抽取(Extraction)

接下来我们尝试处理稍微复杂一点的结构化信息抽取任务:

"Joe is 30, his mom is Martha" —— 从中提取出人物姓名与年龄。

定义嵌套结构

本次任务需要抽取多个人物信息,因此我们将构建一个嵌套的结构体:外层是包含多个 Person 的 Information,内层是每个人的 name 和可选的 age 字段。

from typing import List, Optional
from pydantic import BaseModel, Field

class Person(BaseModel):
    name: str = Field(description="人物姓名")
    age: Optional[int] = Field(description="人物年龄,可缺失")

class Information(BaseModel):
    people: List[Person] = Field(description="人物信息列表")

这一步是关键,Pydantic 允许我们通过这种嵌套结构清晰表达所需数据的层级关系。

注册为Function并绑定模型

有了数据结构后,我们仍需将其注册为函数形式供大模型调用,并指定函数名称:

info_fn = convert_to_openai_function(Information)
extraction_model = model.bind(functions=[info_fn], function_call={"name": "Information"})

这样,模型收到输入后就会依据我们预设的结构,返回 people 字段对应的所有人物信息。

构造Prompt并执行链条

我们设置提示词,指导模型在抽取信息时不进行猜测,只输出明确表达的信息:

prompt = ChatPromptTemplate.from_messages([
    ("system", "提取文本中所有人物姓名和年龄"),
    ("user", "{input}")
])

extraction_chain = prompt | extraction_model | JsonOutputFunctionsParser()

执行调用:

print(extraction_chain.invoke({"input": "Joe is 30, his mom is Martha"}))

输出结构如下:

{'people': [{'name': 'Joe', 'age': 30}, {'name': 'Martha', 'age': None}]}

可以看到大模型成功提取出了两个人的信息,一个是Joe,对应是30岁,另一个是Martha,没有年龄信息。假如我们只想要对应的人物信息而不需要people的话,我们也可以使用 JsonKeyOutputFunctionsParser(key_name="people") 获取更简洁的列表格式结果。

from langchain.output_parsers.openai_functions import JsonKeyOutputFunctionsParser

extraction_chain = prompt | extraction_model | JsonKeyOutputFunctionsParser(key_name="people")

print(extraction_chain.invoke({"input": "Joe is 30, his mom is Martha"}))

输出结构如下:

[{'name': 'Joe', 'age': 30}, {'name': 'Martha', 'age': None}]

这样我们就成功完成提取任务信息的任务啦!

完整代码如下所示:

from langchain_openai import ChatOpenAI
from langchain_core.utils.function_calling import convert_to_openai_function
from pydantic import BaseModel, Field
from langchain.prompts import ChatPromptTemplate
from langchain.output_parsers.openai_functions import JsonOutputFunctionsParser
from typing import List, Optional
from langchain.output_parsers.openai_functions import JsonKeyOutputFunctionsParser

model = ChatOpenAI(
    model="qwen-turbo",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key="api_key"# 你的 API key
)

# class Tagging(BaseModel):
#    sentiment: str = Field(description="文本的情感倾向,取值为 `pos`(正面)、`neg`(负面)或 `neutral`(中性)")
#    language: str = Field(description="文本所用语言(ISO 639-1 语言代码)")
    
# convert_to_openai_function(Tagging)

# prompt = ChatPromptTemplate.from_messages([
#     ("system", "请仔细思考并按照要求对文本进行标注"),
#     ("user", "{input}")
# ])

# model_with_functions = model.bind(
#     functions=[convert_to_openai_function(Tagging)],
#     function_call={"name": "Tagging"}
# )

# tagging_chain = prompt | model_with_functions
# print(tagging_chain.invoke({"input": "I love langchain"}))

# tagging_chain = prompt | model_with_functions | JsonOutputFunctionsParser()
# print(tagging_chain.invoke({"input": "I love langchain"}))

# --------------------------

class Person(BaseModel):
    name: str = Field(description="人物姓名")
    age: Optional[int] = Field(description="人物年龄,可缺失")

class Information(BaseModel):
    people: List[Person] = Field(description="人物信息列表")

info_fn = convert_to_openai_function(Information)
extraction_model = model.bind(functions=[info_fn], function_call={"name": "Information"})
prompt = ChatPromptTemplate.from_messages([
    ("system", "提取文本中所有人物姓名和年龄"),
    ("user", "{input}")
])

extraction_chain = prompt | extraction_model | JsonOutputFunctionsParser()
print(extraction_chain.invoke({"input": "Joe is 30, his mom is Martha"}))

extraction_chain = prompt | extraction_model | JsonKeyOutputFunctionsParser(key_name="people")

print(extraction_chain.invoke({"input": "Joe is 30, his mom is Martha"}))

总结

通过这篇教程,我们基于LangChain与OpenAI的Function Calling机制,完成了两个典型任务:

  • 文本标签识别(Tagging)

  • 嵌套结构信息抽取(Extraction)

你不仅学会了如何设计Pydantic模型、注册为函数、绑定模型、执行调用,还掌握了如何使用解析器解析函数结果,极大提升了对大模型调用逻辑的理解。

💡 下节预告:网页抽取与多段文本分析

我们将进一步挑战真实内容处理任务:

  • 如何从整篇网页中提取结构化信息?

  • 如何批量提取被引用的论文标题与作者?

  • 面对数千字长文,如何用 LangChain 分段、并行处理?

 

 如何学习AI大模型?

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;

第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;

第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;

第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;

第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;

第六阶段: 以SD多模态大模型为主,搭建了文生图小程序案例;

第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。


👉学会后的收获:👈
• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。


1.AI大模型学习路线图
2.100套AI大模型商业化落地方案
3.100集大模型视频教程
4.200本大模型PDF书籍
5.LLM面试题合集
6.AI产品经理资源合集

👉获取方式:
😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐