大模型Tools(Function Calling)实用性分析 - 以媒体信息解析为例
一、背景
作为一个喜欢收集影视资源的人,笔者面临的一个任务是:从文件名中解析出格式化的媒体信息(信息源统一为The Movie Database (TMDB)),方便整理文件,如:
文件名 | 格式化信息 |
---|---|
Young.Woman.and.the.Sea.2024.2160p.DSNP.WEB-DL.H265.HDR.DDP5.1.Atmos-ADWeb.mkv | {'title': '泳者之心', 'genre': 'movie', 'year': 2024} |
【動畫瘋】物語系列 第外季&第怪季[9][1080P].mp4 | {'title': '物语系列', 'genre': 'tv(anime)', 'year': 2009, 'tv_season_num': 5, 'tv_episode': 9} |
那么,在给定文件名的情况下,怎么用大语言模型(LLM,以下简称大模型) + TMDB API来完成媒体信息的解析工作呢?这篇文章应运而生。
当然,解析媒体信息 + 整理媒体文件(或者说媒体文件刮削),已经有很多现成的解决方案,如
nas-tools
、jellyfin
,笔者更多是想探索大模型的可能性。
1 |
|
二、方案选择
从文件名
到媒体信息
,大致分为这几步:
从文件名中解析关键字,去tmdb搜索,获得标题、分类信息;
如果是电视剧且标题里没有季度编号,则需要去tmdb查询季度信息,确定这是第几季;
如果是电视剧,还需要从标题里解析这是该季度的第几集。
按这个思路,大概有3种解决方案:
1. 代码控制流程
调用tmdb api等步骤由代码控制,大模型只负责
- 从文件名中解析出标题、季度信息、集数信息;
- 当tmdb搜出多个结果时,选择最匹配的一个;
- 当tmdb查询到季度信息后,选择最匹配的一个。
代码开发量较大,没有用到大模型的规划能力。不考虑该方案。
2. 定义函数+Tools调用
我们可以定义一些函数:搜索tmdb的函数、查询tv季度信息的函数,传入文件名后让大模型判断需要调用哪些函数,最终得到媒体信息。
OpenAI在2023年6月发布了Function Calling,随后各家大模型厂商开始跟进。目前该功能逐渐改名为Tools
。代码示例:
1 |
|
3. 定义函数+JSON调用
Tools的核心逻辑是将函数声明/函数调用放到一个单独的字段来传递。优点是在人机对话时能隐藏函数调用的细节;缺点是对模型能力(更直接地说是训练/微调的数据集)有更高要求。笔者主要是API场景,更喜欢将函数声明/函数调用放到message记录内,对模型兼容性更好:
1 |
|
三、代码
1. 定义函数
首先定义两个函数:搜索tmdb、查询季度信息。函数都很简单,调用tmdb API + 将API返回值转成想要的格式。
注意点:由于tmdb的search api,关键字参数不支持传入年份,所以在将函数定义传给大模型时需要强调这一点(见下文)。
1 |
|
2. Tools调用
Tools算是一个标准格式,笔者参考Deepseek的文档(Function Calling | DeepSeek API Docs)编写了如下代码。考虑到用JSON格式返回会降低大模型的推理能力,所以笔者这里先用自然语言和大模型交互,有结果后再调用一次大模型将媒体信息提取为JSON,用消耗更多token换取准确率。
1 |
|
3. JSON调用
JSON调用的版本相比Tools调用的版本更简洁,主要是:
- 传给大模型的函数定义,从结构上来说更简洁
- 大模型直接返回JSON格式的函数调用,解析起来更简单
- 大模型始终输出JSON,不需要在结束后再解析一次。
关键点:函数的返回值在传给大模型之前,最好加上前缀强调来提升准确率:res = f"调用{jr['function']}的返回值:\n{res}"
1 |
|
四、测试结果
测试目标是让大模型输出格式化的媒体信息:
文件名 | 格式化信息 |
---|---|
Young.Woman.and.the.Sea.2024.2160p.DSNP.WEB-DL.H265.HDR.DDP5.1.Atmos-ADWeb.mkv | {'title': '泳者之心', 'genre': 'movie', 'year': 2024} |
【動畫瘋】物語系列 第外季&第怪季[9][1080P].mp4 | {'title': '物语系列', 'genre': 'tv(anime)', 'year': 2009, 'tv_season_num': 5, 'tv_episode': 9} |
笔者选用了四个低价的大模型来测试,最贵是的gpt-4o-mini,输出$0.6/1M tokens:
- deepseek-chat的api (v2.5 09/05更新),低价+开源
- qwen-plus-latest的api (09/19更新),低价+基于开源的qwen 2.5 72B
- gpt-4o-mini的api (07/18更新),低价+国际大厂
- gemini-1.5-flash (04/13更新),低价+国际大厂
文件名 | 方案 | 模型 | token消耗 | 结果 |
---|---|---|---|---|
Young.Woman.and.the.Sea.2024.2160p.DSNP.WEB-DL.H265.HDR.DDP5.1.Atmos-ADWeb.mkv | Tools调用 | deepseek-chat | 1141 | 成功 |
同上 | Tools调用 | qwen-plus-latest | 1481 | 部分成功,标题解析成了泳者之心 (Young Woman and the Sea) |
同上 | Tools调用 | gpt-4o-mini | 747 | 成功 |
同上 | Tools调用 | gemini-1.5-flash | 610 | 部分成功,标题解析成了Young.Woman.and.the.Sea |
【動畫瘋】物語系列 第外季&第怪季[9][1080P].mp4 | Tools调用 | deepseek-chat | 2821 | 成功,但不稳定(超时/第二轮时无法触发tools调用等) |
同上 | Tools调用 | qwen-plus-latest | 1856 | 成功 |
同上 | Tools调用 | gpt-4o-mini | 1667 | 部分成功,未解析出第几季/第几集 |
同上 | Tools调用 | gemini-1.5-flash | 1265 | 失败,tmdb api调用成功但结果解析很糟糕 |
Young.Woman.and.the.Sea.2024.2160p.DSNP.WEB-DL.H265.HDR.DDP5.1.Atmos-ADWeb.mkv | JSON调用 | deepseek-chat | 652 | 成功 |
同上 | JSON调用 | qwen-plus-latest | 575 | 成功 |
同上 | JSON调用 | gpt-4o-mini | 559 | 成功 |
同上 | JSON调用 | gemini-1.5-flash | 587 | 成功 |
【動畫瘋】物語系列 第外季&第怪季[9][1080P].mp4 | JSON调用 | deepseek-chat | 1158 | 成功 |
同上 | JSON调用 | qwen-plus-latest | 942 | 成功 |
同上 | JSON调用 | gpt-4o-mini | 540 | 部分成功,未解析出第几季/第几集 |
同上 | JSON调用 | gemini-1.5-flash | 262 | 失败,直接没有调用tmdb api |
五、结论
从大模型对比的角度来看:
qwen-plus-latest
表现最好。价格比deepseek-chat
稍低,但速度更快、效果更好。充分体现了最新开源的qwen 2.5家族的实力。deepseek-chat
在Tools调用场景发挥不稳定,比如解析【動畫瘋】物語系列 第外季&第怪季[9][1080P].mp4
时,虽然知道要调用函数获取季度信息,但却没有按Tools格式输出,导致后续无法衔接:1
{'content': '从搜索结果来看,有两个不同的条目:一个是“物語系列”(2009年,TV动画),另一个是“春风物语”(2023年, 电影)。我们需要的是“物語系列”的信息。\n\n接下来,我们需要获取“物語系列”的详细信息,特别是“第外季”和“第怪季”的相关信息。由于这些季数可能不是标准的季数,我们需要进一步查询以确认。\n\n请调用 `tv_season_info` 函数,传入 `tmdb_id` 为 `46195`, 以获取“物語系列”的季数信息。', 'role': 'assistant', 'tool_calls': None, 'function_call': None}
gpt-4o-mini
表现一般,价格最贵,但容易忽略TV作品的第几季/第几集。gemini-1.5-flash
价格最低,表现也最差。
从Tools使用的角度来看:
- Tools诞生的场景是:在聊天机器人对话过程中,兼顾用户体验和外部函数调用。但在API场景中,“兼顾用户体验”的部分成了累赘。
- 笔者设计的JSON调用模式,对机器间交互设计,在外部函数调用方面比Tools方式效率更高、准确度更高。