大模型问答之时间语义解析方案调研
1. 引入
在处理时间语义解析的任务时,我们需要准确地从用户查询中提取出具体的时间范围,以便能够针对性地检索或分析特定时间段内的信息。
比如用户输入下面这样的问题:
- 近期有哪些值得看的娱乐新闻?
- 最近一年有哪些值得看的娱乐新闻?
- 180天之内有哪些值得看的娱乐新闻?
- 2020年儿童节到2023年万圣节之间有哪些值得看的娱乐新闻?
如何提取这种问题的时间范围呢?
2. 时间语义解析方案
在时间语义解析领域,针对如何有效提取和理解时间表达,存在多种潜在方案,每种方案都有其独特的优势与局限性。
- 穷举关键词法
此方法通过预设一个包含时间相关关键词的列表,来尝试匹配文本中的时间信息。其优势在于实现简单直接,但显然存在显著的缺点,即难以覆盖所有可能的时间表达形式,尤其是那些非标准或新颖的表达方式,因此容易导致信息遗漏。
- 命名实体识别(NER)
NER是一种自然语言处理技术,专门用于识别文本中的命名实体,如人名、地名、时间等。通过从头开始标注训练数据并构建模型,NER能够较为准确地识别出文本中的时间表达。此方案的优点在于实现快速且灵活,能够适应多种语言和时间表达形式。然而,其成本也相对较高,包括标注大量高质量训练数据的时间和人力成本,以及模型训练所需的计算资源。
-
大型语言模型(LLM)
利用大型语言模型进行时间语义解析是一种潜力巨大的方法。然而,这种方法的一个显著缺点是模型回复耗时较长,在很多低成本领域,这个方案太重了。 -
正则表达式(Regex)
正则表达式是一种强大的文本处理工具,通过定义一系列字符模式来匹配和提取文本中的特定信息。在时间语义解析中,正则表达式可以被用来设计一系列规则,以捕获文本中的时间表达。相比于穷举关键词法,正则表达式具有更高的灵活性和准确性,能够匹配更多样化的时间表达形式。然而,其缺点同样在于难以覆盖所有可能的情况,特别是当时间表达形式变得复杂或不规则时,可能会导致信息遗漏。尽管如此,正则表达式在处理结构化或半结构化文本时通常表现出色,且实现成本相对较低。
现有工具/方案,也基本是上面几种方案(或者多个方案的组合)的思路。下面会选取其中几个工具做些测评(ubuntu22.04+python3.11)。
3. 实测jionlp
jionlp,开源项目见参考1。从其解析时间的源码(参考2)中,可以看到,它主要是通过正则表达式、关键词加上一些节假日规则”,来实现时间语义解析的。它能做到“精确匹配”、“模糊匹配”等不同的规则匹配。下面是几个实测的例子:
(1)
import jionlp as jio
jio.parse_time('近期有哪些值得看的娱乐新闻? ')
运行报错ValueError: can not parse the string
近期有哪些值得看的娱乐新闻?`.
(2)
import jionlp as jio
jio.parse_time('最近一年有哪些值得看的娱乐新闻? ')
输出
{'type': 'time_span','definition': 'blur','time': ['2023-08-29 00:00:00', '2024-08-28 13:46:21']}
对于这个例子,解析是正确的,能给出解析后的具体的时间范围。
(3)
import jionlp as jio
jio.parse_time('2020年儿童节到2023年万圣节之间有哪些值得看的娱乐新闻? ')
输出
{'type': 'time_span','definition': 'accurate','time': ['2020-06-01 00:00:00', '2023-10-31 23:59:59']}
对于这个例子,解析是正确的,能给出解析后的具体的时间范围。
4. 实测Time_NLP
参考3给出了Time_NLP的链接,这个项目没法用pip安装,需要下载后,作为第三方库导入使用。原理上,从源码来看(参考4,5,6),他也是利用正则表达式,结合一些节假日的定义,来做到的。
(1)
import sys
sys.path.append("Time_NLP/")
from TimeNormalizer import TimeNormalizer
tn = TimeNormalizer()
res = tn.parse(target="近期有哪些值得看的娱乐新闻? ")
print(res)
输出:
{"error": "no time pattern could be extracted."}
(2)
import sys
sys.path.append("Time_NLP/")
from TimeNormalizer import TimeNormalizer
tn = TimeNormalizer()
res = tn.parse(target="最近一年有哪些值得看的娱乐新闻? ")
print(res)
输出:
{"type": "timedelta", "timedelta": {"year": 1, "month": 0, "day": 0, "hour": 0, "minute": 0, "second": 0}}
对于这个例子,解析是正确的,能给出解析后的具体的时间范围。
(3)
import sys
sys.path.append("Time_NLP/")
from TimeNormalizer import TimeNormalizer
tn = TimeNormalizer()
res = tn.parse(target="2020年儿童节到2023年万圣节之间有哪些值得看的娱乐新闻? ")
print(res)
输出:
{"type": "timespan", "timespan": ["2020-06-01 00:00:00", "2023-01-01 00:00:00"]}
这个例子中,儿童节提取正确,万圣节提取错误。
5. 总结
从初步测试结果来看,jionlp
比Time_NLP
效果好,而且Time_NLP
已经很久没有更新了。但是Time_NLP
有java版本(参考8),而且还有升级后的java版本xk-time
(参考7,xk-time是在Time_NLP基础上做了改进)。但是jionlp
只有python版本。
6. 参考
- jionlp. https://github.com/dongrixinyu/JioNLP
- https://github.com/dongrixinyu/JioNLP/blob/master/jionlp/gadget/time_parser.py
- https://github.com/zhanzecheng/Time_NLP
- https://github.com/zhanzecheng/Time_NLP/blob/master/resource/holi_lunar.json
- https://github.com/zhanzecheng/Time_NLP/blob/master/resource/holi_solar.json
- https://github.com/zhanzecheng/Time_NLP/blob/master/resource/regex.txt
- https://github.com/xkzhangsan/xk-time
- https://github.com/shinyke/Time-NLP