惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

B
Blog RSS Feed
Spread Privacy
Spread Privacy
T
Threatpost
C
Cisco Blogs
P
Palo Alto Networks Blog
AI
AI
Cyberwarzone
Cyberwarzone
NISL@THU
NISL@THU
P
Privacy & Cybersecurity Law Blog
G
GRAHAM CLULEY
Simon Willison's Weblog
Simon Willison's Weblog
T
Tor Project blog
Latest news
Latest news
AWS News Blog
AWS News Blog
D
Docker
S
SegmentFault 最新的问题
博客园 - 聂微东
WordPress大学
WordPress大学
Vercel News
Vercel News
S
Securelist
爱范儿
爱范儿
J
Java Code Geeks
Know Your Adversary
Know Your Adversary
S
Schneier on Security
Hugging Face - Blog
Hugging Face - Blog
F
Fortinet All Blogs
Last Week in AI
Last Week in AI
D
DataBreaches.Net
宝玉的分享
宝玉的分享
D
Darknet – Hacking Tools, Hacker News & Cyber Security
MongoDB | Blog
MongoDB | Blog
Engineering at Meta
Engineering at Meta
K
Kaspersky official blog
美团技术团队
博客园 - 叶小钗
阮一峰的网络日志
阮一峰的网络日志
量子位
博客园_首页
Attack and Defense Labs
Attack and Defense Labs
S
Secure Thoughts
Google Online Security Blog
Google Online Security Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
腾讯CDC
T
Threat Research - Cisco Blogs
雷峰网
雷峰网
有赞技术团队
有赞技术团队
www.infosecurity-magazine.com
www.infosecurity-magazine.com
P
Privacy International News Feed
S
Security Affairs

元视角

.NET 生态下的 Agent 框架选型:从 ReAct 到原生推理 - 元视角 从「能用」到「好用」:LLM 流式响应实现方式的探索之路 - 元视角 当我用 2000 条聊天记录,让 AI 为我画一幅自画像 - 元视角 基于 Supabase 的 AI 应用开发探索 - 元视角 微博 × MCP:社交媒体新玩法解锁 - 元视角 四点钟海棠花未眠 - 元视角 Semantic Kernel × MCP:智能体的上下文增强探索 - 元视角 基于 K-Means 聚类分析实现人脸照片的快速分类 - 元视角 容器技术驱动下的代码沙箱实践与思考 - 元视角 温故而知新:后端通用查询方案的再思考 - 元视角 浅议 CancellationToken 在前后端协同取消场景中的应用 - 元视角 Semantic Kernel 视角下的 Text2SQL 实践与思考 - 元视角 关于 ChatGPT 的流式传输,你需要知道的一切 - 元视角 RAG 的是与非、Rewrite 和 Rerank - 元视角 使用 EFCore 和 PostgreSQL 实现向量存储及检索 - 元视角 基于 LLaMA 和 LangChain 实践本地 AI 知识库 - 元视角 使用 llama.cpp 在本地部署 AI 大模型的一次尝试 - 元视角 如何为 Git 配置多个 SSH Key - 元视角 C# 使用 LibUsbDotNet 实现 USB 设备检测 - 元视角 基于 C# 实现样式与数据分离的打印方案 - 元视角 基于 SVG 的图形交互方案实践 - 元视角 前端视频播放技术概览 - 元视角 温故而知新,再话 Python 动态导入 - 元视角 视频是不能 P 的系列:使用 Milvus 实现海量人脸快速检索 - 元视角 GDI+下字体大小自适应方案初探 - 元视角 小爱音箱集成 ChatGPT 的不完全教程 - 元视角 程序员视角下的三体世界随想 - 元视角 关于 Docker 容器配置信息的渐进式思考 - 元视角 在 Docker 容器内集成 Crontab 定时任务 - 元视角 为你的服务器集成 LDAP 认证 - 元视角 似花还似非花 - 元视角 视频是不能 P 的系列:使用 Dlib 实现人脸识别 - 元视角 浅议分布式链路追踪与日志的整合 - 元视角 关于 Git 大文件上传这件小事 - 元视角 .NET 进程内队列 Channel 的入门与应用 - 元视角 使用 Fody 实现 .NET 的静态编织 - 元视角 .NET Core + ELK 搭建可视化日志分析平台(下) - 元视角 聊一聊前端图片懒加载背后的故事 - 元视角 支持外部链接跳转的 Vue Router 扩展实现 - 元视角 视频是不能 P 的系列:OpenCV 和 Dlib 实现表情包 - 元视角 不得不说的 ASP.NET Core 集成测试 - 元视角 再议 DDD 视角下的 EFCore 与 领域事件 - 元视角 Vue.js 前端项目容器化部署实践极简教程 - 元视角 再见,人间四月天 - 元视角 Python 图像风格化迁移助力画家梦想 - 元视角 利用 ASP.NET Core 中的标头传播实现分布式链路追踪 - 元视角 利用 gRPC 实现文件的上传与下载 - 元视角 七种武器:延迟队列的原理和实现总结 - 元视角 gRPC 流式传输极简入门指南 - 元视角 Envoy 集成 Jaeger 实现分布式链路追踪 - 元视角 浅议非典型 Web 应用场景下的身份认证 - 元视角 gRPC 借助 Any 类型实现接口的泛化调用 - 元视角 分布式丛林探险系列之 Redis 集群模式 - 元视角 分布式丛林探险系列之 Redis 主从复制模式 - 元视角 通过 Python 预测 2021 年双十一交易额 - 元视角 gRPC 搭配 Swagger 实现微服务文档化 - 元视角 SSL/TLS 加密传输与数字证书的前世今生 - 元视角 使用 Python 自动识别防疫健康码 - 元视角 你不可不知的容器编排进阶技巧 - 元视角 ASP.NET Core 搭载 Envoy 实现 gRPC 服务代理 - 元视角 再话 AOP,从简化缓存操作说起 - 元视角 ASP.NET Core 搭载 Envoy 实现微服务身份认证(JWT) - 元视角 ASP.NET Core 搭载 Envoy 实现微服务的监控预警 - 元视角 ASP.NET Core 搭载 Envoy 实现微服务的反向代理 - 元视角 ASP.NET Core gRPC 打通前端世界的尝试 - 元视角 EFCore 实体命名约定库:EFCore.NamingConventions - 元视角 ASP.NET Core gRPC 集成 Polly 实现优雅重试 - 元视角 ASP.NET Core gRPC 健康检查的探索与实现 - 元视角 ASP.NET Core gRPC 拦截器的使用技巧分享 - 元视角 SnowNLP 使用自定义语料进行模型训练 - 元视角 使用 HttpMessageHandler 实现 HttpClient 请求管道自定义 - 元视角 ABP vNext 的实体与服务扩展技巧分享 - 元视角 ABP vNext 对接 Ant Design Vue 实现分页查询 - 元视角 源代码探案系列之 .NET Core 跨域中间件 CORS - 元视角 源代码探案系列之 .NET Core 限流中间件 AspNetCoreRateLimit - 元视角 源代码探案系列之 .NET Core 并发限制中间件 ConcurrencyLimiter - 元视角 通过 EmbededFileProvider 实现 Blazor 的静态文件访问 - 元视角 低代码,想说爱你不容易 - 元视角 记一次失败的 ThoughtWorks 面试经历 - 元视角 从 C# 1.0 到 C# 9.0,历代 C# 语言特性一览 - 元视角 通过 Python 分析 2020 年全年微博热搜数据 - 元视角 基于 Python 和 Selenium 实现 CSDN 一键三连自动化 - 元视角 使用多线程为你的 Python 爬虫提速的 N 种姿势,你会几种? - 元视角 实现网页长截图的常见思路总结 - 元视角 温故而知新,由 ADO.NET 与 Dapper 所联想到的 - 元视角 视频是不能 P 的系列:OpenCV 人脸检测 - 元视角 作为技术宅的我,是这样追鬼滅の刃的 - 元视角 使用 Python 抽取《半泽直树》原著小说人物关系 - 元视角 厉害了!打工人用 Python 分析西安市职位信息 - 元视角 使用 dotTrace 对 .NET 应用进行性能分析与优化 - 元视角 一道 HashSet 面试题引发的蝴蝶效应 - 元视角 基于选项模式实现.NET Core 的配置热更新 - 元视角 Dapper.Contrib 在 Oracle 环境下引发 ORA-00928 异常问题的解决 - 元视角 .NET Core 中对象池(Object Pool)的使用 - 元视角 利用 MySQL 的 Binlog 实现数据同步与订阅(下):EventBus 篇 - 元视角 利用 MySQL 的 Binlog 实现数据同步与订阅(中):RabbitMQ 篇 - 元视角 利用 MySQL 的 Binlog 实现数据同步与订阅(上):基础篇 - 元视角 记一次从已损坏的 Git 仓库中找回代码的经历 - 元视角 .NET Core 原生 DI 扩展之属性注入实现 - 元视角 .NET Core 原生 DI 扩展之基于名称的注入实现 - 元视角
后 GPT 时代,NLP 不存在了? - 元视角
飞鸿踏雪 · 2023-05-13 · via 元视角

在刘慈欣老师的《三体》小说中,整个故事是以杨冬的死亡线索展开的,而她自杀的原因是物理学不存在了。随着 GPT-4 的发布,『NLP已死』和『NLP不存在了』的声音开始不绝于耳。如果说杨冬认为物理学被颠覆源于智子的“欺骗”,那么,现在的大型语言模型对于 NLP 的冲击,实际上改变了AI与最终用户互动的方式。传统的 NLP 技术方向涵盖了信息抽取、文本挖掘、机器翻译、语音合成、语音识别、语义理解、句法分析,这些都被视为自然语言处理的中间任务。因此,传统的 NLP 模式是在每个领域中提供各种不同的工具。当需要对自然语言进行处理时,你不得不将这些不同的工具结合起来,就像博主曾经使用过的结巴分词、SnowNLP、词袋模型、情感分析、TF-IDF一样。然而,现在的大型语言模型更像是一个直接面对最终任务的“智者”,跳过了这些中间任务。因为我们最终的目的就是要让程序产生智能,并让人类相信它能够“理解”他们的意图。显然,在这一点上,ChatGPT 和 Midjourney 都做到了。作为非科班的程序员,我无法科学、客观地评判 LLM 和 NLP 的优劣。但是我想分享一下我在开发 “贾维斯” 过程中获得的一点心得,希望对大家有所启发。

Hey Jarvis

在将小爱同学接入 ChatGPT 以后,我开始思考怎么样在智能和功能上取得平衡,尽管 ChatGPT 提升了小爱同学在聊天方面的智能,可这同时破坏了当下智能音箱普遍使用的“指令集”,你无法运用 ChatGPT 的这种“聪慧”让它真正地帮你做点事情。所以,我大概率要再次发明“智能音箱”,可我想知道,有了 ChatGPT 的加持以后,它到底能达到什么样的智能水平?带着这样一个想法,我开始从头编写贾维斯,一个基于 ChatGPT 的人工智能管家,其灵感来源于钢铁侠的人工智能管家 Jarvis。目前,它可以查询日期/时间、检索信息、播放音乐、控制米家/电脑、打开应用、讲笑话、查询天气、编程。以下是我在 Bilibili 上发布的视频演示:

你可能会好奇这些功能都是如何实现的?请允许我做一个简单说明,下面是“贾维斯”的整体设计思路:

贾维斯整体设计思路说明 贾维斯整体设计思路说明

从整体而言,整个程序并不算特别复杂,因为语音唤醒、语音识别、语音合成这些均已有非常成熟的方案。在接入 ChatGPT 以后,我开始尝试为它扩展更多的功能。这个时候,我了解到自然语言理解(NLU)的这个方向,并且它依然属于自然语言处理(NLP)这个范畴,更具体的关键词则是意图识别或者意图提取。以查询日期这个功能为例,我只需要在某个函数上添加“路由”,即可为贾维斯设计不同的“技能”:

@trigger.route(keywords=['查询日期','询问日期','日期查询'])
def report_date(input):
    now = datetime.datetime.now()
    week_list = ['星期一','星期二','星期三','星期四','星期五','星期六','星期日']
    formated = now.strftime('%Y年%m月%d日')
    week_day = week_list[now.weekday()]
    history = today_on_history()
    if history != None:
        return f'今天是{formated}{week_day}{history}。'
    else:
        return f'今天是{formated}{week_day}。'

此时,问题就被转化为如何识别或者提取一句话中的真实意图。坦白地讲,面对人类这种口是心非的动物,想要了解其真实意图是非常困难的。譬如,人类都希望别人能够“懂我”,可没有人会喜欢被别人一眼看穿。因此,我们这里讨论的意图,特指那些动宾结构的指令型用语,例如:打开客厅的灯、查询明天的天气等等。不论屏幕前的你对 AI 持何种态度,我想说的是,AI 已然参与到我日常的编程和写作中,这正是我开发贾维斯的动力所在,我希望它能参与到更多的事项中去,甚至想让它取代家里的小爱同学。

基于 ChatGPT 实现意图提取

对笔者而言,在接触到 ChatGPT 以后,编程语言就仿佛进入了一个新的时代——魔法时代。因为无论你需要大语言模型帮你做什么,你要做的第一件事情就是编写 Prompt。而关于这件事情本身,则像极了魔法师在施法前吟唱咒语。所以,你说未来会出现那种被称之为“魔法吟唱师”的职业吗?当然,更有意思的点在于,如果说目前的编程语言都是过程式的,那么,在进入魔法时代以后,这一切就会变成描述式的。关于意图提取这个话题,你打算怎么样向 AI 解释它呢?下面开始我的尝试:

我想让你扮演我的自然语言处理工具,当我告诉你一句话的时候,你可以对它进行分词、句法分析、词性分析、上下文分析、主题建模/抽取,你可以自由地使用结巴分词、nltk 或者是 SnowNLP 这些工具,你需要猜测我这句话中的意图,并用下面的形式表示出来:

{
  "query": "查询许嵩的资料",
  "intent": {
      "name": "查询",
      "confidence": 0.95
  },
  "entities": [
  {
      "entity": "name",
      "value": "许嵩",
      "start": 2,
      "end": 4,
      "confidence": 0.98
  }]
}

其中,query 字段表示原始查询文本,intent 字段表示查询意图,entities 字段表示本次查询中提取的实体信息。在这个示例中,意图为查询,置信度为0.95,实体为人名,值为“许嵩”,起始位置为2,结束位置为4,置信度为0.98。你只需要返回给我这样一段 JSON,不需要任何冗余的信息。需要注意的是,你要对相似的意图进行归类和合并,使用一个统一的意图进行描述。我的问题是:

如你所见,这是一段非常复杂的提示词,采用了经典的 Markdown 格式,借此告诉 ChatGPT 它需要做什么样的事情、以及期望它返回的数据格式。通常情况下,我们可以使用 requests 库来调用 ChatGPT 的 API 接口:

# 一个小技巧,使用三个单引号来处理多行文本
prompt = '''在这里填入你的提示词'''

# 定义请求头
headers = {
  "Content-Type": "application/json",
  "Authorization": "Bearer <Your OpenAI API KEY>",
}

# 定义请求体
query = '播放许嵩的断桥残雪'
query = prompt + query

payload = {
  "model": "gpt-3.5-turbo",
  "messages": [{"role": "user", "content": query}]
}

# 调用 ChatGPT API
r = requests.post('https://api.openai.com/v1/completions', headers=headers, json=data)
data = r.json()
content = data.get("choices")[0]["message"]["content"]
# 由于返回的是 JSON,需要再做一次反序列化
result = json.loads(content) 

在将我的指令和提示词一起发送给 ChatGPT 后,我实际上获得了一个具备意图提取能力的 API 接口。虽然我没有使用传统 NLP 工具或技术,但我确实实现了类似的功能。我测试过 ChatGPT 的英文翻译效果,发现它的翻译效果甚至比主流的翻译工具要好很多。因此,无论传统 NLP 如何努力,似乎都难以与之匹敌,这大抵解释了为什么人们会发出“NLP已死”的声音。你还记得刘慈欣老师书中的“降维打击”这一概念吗?传统 NLP 一直致力于优化模型和算法,即使 GPT 使用的技术并不算先进。然而,在海量数据和大规模算力面前,GPT 最终呈现出来的效果比这些方案要好得多,这确实是一种奇迹。以下是博主通过 ChatGPT 提取出来的意图:

通过 ChatGPT 提取意图 通过 ChatGPT 提取意图

那么,这个方案是否就完美无缺呢?答案显然是否定的,一个最为明显的问题是,ChatGPT 对意图的分类非常随意,例如,查询日期和日期查询,是同一种含义的不同表达,属于近义词,可是 ChatGPT 并不会主动合并这些相似的结果,即使你在提示词中已经提及了这一点。那么,该如何优化这个问题呢?一种可行的方案是在提示词中告诉它你期望的意图分类,如信息查询、天气查询、设备控制…等等。除此之外,这段提示词的长度大概为1000个字符,大概会消耗 100 至 200 个左右的 Token,虽然支持多模态的 GPT-4 变得更强大了,可它的价格是 GPT-3.5 的 15 到 60 倍左右,因此,从经济成本考虑,这个基于 ChatGPT 的意图提取方案,在未来产生的费用可能会越来越高。当然,如果你能训练出比 GPT-3.5 更强大的大语言模型,这个问题就不再是一个问题啦!

基于 Rasa NLU 实现意图提取

也许,你在视频注意到了,当我向贾维斯下达控制智能家居的指令时,有时候它并不能正确地理解我地意图。于是,我开始尝试回归到传统 NLP 的思路。在这个过程中,我了解到了 Rasa NLU 这个项目,这是一个致力于构建 AI 助手的开源框架,你可以提供它提供的各种能力训练出一个聊天机器人。当然,我最感兴趣的还是它提供的自然语言理解(NLU)能力,我打算借助于这一框架,训练出一个可以离线使用的意图提取器。因为只有这样,你才能深刻地理解 LLM 和 NLP 的区别在哪里。参照官方教程,在正式开始训练前,你至少应该做好以下准备:

  • 一个 Python 3.9 的环境,建议使用 virtualenv 来管理你的虚拟环境
  • 安装 CMake 环境,建议将其添加至操作系统环境变量中
  • 下载中文词向量模型文件 total_word_feature_extractor_zh.dat,提取码:g54u

接下来,安装必要的依赖项。其中,MITIE 建议通过源代码来安装:

python -m pip install rasa jieba scikit-learn
# 从源代码安装 MITIE,直接安装失败率非常高
python -m pip install git+https://github.com/mit-nlp/MITIE.git

Rasa 的训练主要分为 Core 和 NLU 两个部分。其中,Core 这部分主要用于聊天机器人的训练,换句话说,只有当你需要实现一个功能完备的聊天机器人的时候,你才需要针对这部分进行训练。考虑到,我们这里仅仅是为了使用 Rasa 提供的 NLU 能力。因此,我们只需要训练 NLU 这部分即可。下面是笔者参照官方文档编写的训练数据, 在 Rasa 1.0 以及 Rasa 2.0 版本中,通常使用 JSON 和 Markdown 格式来编写训练数据,而在 Rasa 3.0 中,我们有了新的选择——YAML,下面是一个简单的示例:

version: "3.1"

nlu:
- intent: greet
  examples: |
    - 你好
    - 哈喽
    - 嗨
    - 嘿
    - 早上好
    - 晚上好
    - 早安
    - 晚安    

- intent: query_weather
  examples: |
    - [今天]{"entity": "date"}的天气怎么样
    - [明天]{"entity": "date"}的天气怎么样
    - [后天]{"entity": "date"}的天气怎么样
    - [今天]{"entity": "date"}下雨吗
    - [明天]{"entity": "date"}下雨吗
    - [后天]{"entity": "date"}下雨吗
    - [今天]{"entity": "date"}的气温是多少
    - [明天]{"entity": "date"}的气温是多少
    - [后天]{"entity": "date"}的气温是多少
    - 帮我查询一下[今天]{"entity": "date"}的天气
    - 帮我查询一下[明天]{"entity": "date"}的天气
    - 帮我查询一下[后天]{"entity": "date"}的天气    

- intent: query_time
  examples: |
    - 几点了
    - 现在几点
    - 告诉我[时间]{"entity": "time"}
    - 查询[时间]{"entity": "time"}    

- intent: query_date
  examples: |
    - [今天]{"entity": "date"}几号
    - [明天]{"entity": "date"}几号
    - [后天]{"entity": "date"}几号
    - [今天]{"entity": "date"}周几
    - [明天]{"entity": "date"}周几
    - [后天]{"entity": "date"}周几
    - [今天]{"entity": "date"}星期几
    - [明天]{"entity": "date"}星期几
    - [后天]{"entity": "date"}星期几
    - 查询[日期]{"entity": "date"}    

- intent: search_info
  examples: |
    - 搜索[周杰伦]{"entity": "name"}的信息
    - 查询[刺客信条]{"entity": "name"}的资料
    - 检索[许嵩]{"entity": "name"}的情况       

完整的训练数据可以在 这里 找到,你可以注意到,在训练数据中博主手动标注出了一部分实体,你必须确保这些词语能被分词组件正确地切分。这一点如何保证呢?事实上,Rasa 采用管道的形式来组织各种各样的组件,例如,在 Rasa 中你可以使用 JiebaTokenizer 或者 MitieTokenizer 对训练数据进行分词。编写 Rasa 配置文件,本质上就是决定选择哪些组件来处理你的训练数据。为了方便大家理解,我做了一个简单的表格供大家参考:

分类组件描述
NLPMitieNLP、SpacyNLP在管道中加载一个预训练的词向量模型
TokenizersWhitespaceTokenizer、JiebaTokenizer、MitieTokenizer、SpacyTokenizer在管道中使用分词组件,对训练数据进行分词
FeaturizersMitieFeaturizer、SpacyFeaturizer、ConveRTFeaturizer、LanguageModelFeaturizer、RegexFeaturizer、CountVectorsFeaturizer、LexicalSyntacticFeaturizer在管道中使用特征化组件,对文本特征进行分类
Intent ClassifiersMitieIntentClassifier、LogisticRegressionClassifier、SklearnIntentClassifier、KeywordIntentClassifier、DIETClassifier、FallbackClassifier在管道中使用意图分类器,识别输入内容的意图
Entity ExtractorsMitieEntityExtractor、SpacyEntityExtractor、SpacyEntityExtractor、DucklingEntityExtractor、RegexEntityExtractor、EntitySynonymMapper在管道中使用实体提取器,提取输入内容中的实体

经过反反复复的训练和测试,博主找到了下面这套最合适的配置文件

language: "zh"
assistant_id: JarvisBot

pipeline:
- name: "MitieNLP"
  model: "data/total_word_feature_extractor_zh.dat"
- name: JiebaTokenizer
  dictionary_path: "data/jieba/"
  "intent_tokenization_flag": false
  "intent_split_symbol": "_"
  "token_pattern": None
- name: "CountVectorsFeaturizer"
  "analyzer": "word"
  "min_ngram": 1
  "max_ngram": 1
  "OOV_token": "_oov_"
  "use_shared_vocab": false
- name: LexicalSyntacticFeaturizer
  "features": [["low", "title", "upper"], ["BOS", "EOS", "low", "upper", "title", "digit"], ["low", "title", "upper"]]
- name: LogisticRegressionClassifier
  max_iter: 100
  solver: lbfgs
  tol: 0.0001
  random_state: 42
  ranking_length: 10
- name: "MitieIntentClassifier"
- name: "MitieEntityExtractor"
- name: "EntitySynonymMapper"

现在,我们只需要通过下面的脚本训练模型即可:

python -m rasa train -c sample_configs/config_jieba_mitie_sklearn.yml --data data/examples/rasa/jarvis_rasa_zh.yml nlu

其中:-c 参数用于指定配置文件、--data参数用于指定训练数据。经博主测试,在普通的 CPU 环境下,完成一次训练大概需要 4 个小时,每次训练后它会在 models 目录生成一个模型文件,在不指定模型名称的情况下,这个模型文件的名称通常是随机生成。当然,你可以使用 --fixed-model-name参数使其固定下来。如下图所示,这是博主“炼丹”过程中保存的截图,希望屏幕前的、比我更懂机器学习的各位,帮我分析一下这个训练是否还有优化空间:

堪比 “炼丹” 的训练过程 堪比 “炼丹” 的训练过程

当模型训练好以后,我们就可以开始测试啦!此时,我们需要执行下面的脚本:

python -m rasa run --enable-api -m models\nlu-20230515-183633-creative-bucket.tar.gz

该命令会在本地运行一个 NLU Server,端口默认为 5005,通常,你可以像下面这样访问它提供的 API 接口:

curl localhost:5005/model/parse -d '{"text":"hello"}'

下面是博主实际测试的结果,个人对这个结果还是挺满意的,如果一定要说缺陷的话,首先,它会把 “王菲的传奇” 这句话切分为 “王菲” 和 “的传奇”,当然,这大概率是没有排除某些停用词的缘故;其次,它不能提取出我们期望的实体,在这个例子中,“孙燕姿”这个实体固然重要,可更重要的应该是“遇见”,这将是接下来优化的一个重点。

测试 Rasa 提供的 NLU 接口 测试 Rasa 提供的 NLU 接口

当然!幸运的是,我们至少解决了当时 ChatGPT 没有解决的问题,因为这些意图的分类都是我们在训练数据中人为规定的,所以,它不会出现意料之外的意图分类,或者是相似的意图分类,就像本文一开始给出的代码示例一样,“查询日期”、“询问日期”、“日期查询” 本质上都是在描述同一件事情,可由于这些分类都是由 ChatGPT 产生的,所以,基于 ChatGPT 的这个方案多少是有点不确定性在里面的,而对于一个 API 来说,相同的输入应该得到相同的结果,从这一点上来看,或许是 Rasa 更胜一筹!

结论

ChatGPT 发布以来,关于被 AI 替代以致于失业的焦虑声音不断涌现,即便是传统的 NLP 亦不能幸免。在开发贾维斯的过程中,博主需要解决意图识别的问题,本文分享了两种解决问题的思路,它们分别是以 ChatGPT 为代表的大语言模型、以 Rasa 为代表的传统 NLP。对于 “NLP 已死”、“NLP 不存在了”这样的观点,笔者的看法是,这实际代表了人工智能的两种方向:通用智能和专业智能。虽然像 ChatGPT 这样的通用型 LLM 表现不俗,但是对于 NLP 的一系列问题,永远依赖于调用一个外部模型注定不可行。在这种情况下,你不可能像 OpenAI 一样投入大量人力、物力去训练一个 LLM。此时,选择 LLaMa 或者 Alpaca 这样的“小”模型就不失为一种明智的选择。此外,现阶段 LLM 的微调、“投喂”数据依然需要 NLP 的知识。也许,正如杨冬所言,并不是物理学不存在了,而是我们认为的物理学不存在了。同样的,像传统 NLP 那样细分的、垂直的子任务会越来越少,而多模态/跨模态的场景和应用会越来越多。如果用一句 100% 正确的废话来描述就是,这是一个机遇与挑战并存的时代!