我们是如何为 ES|QL 重建自动补全功能的
作者:来自 Elastic Drew Tate
Elasticsearch 包含许多新功能,可帮助您为您的用例构建最佳搜索解决方案。深入研究我们的示例笔记本以了解更多信息,开始免费的 Cloud 试用,或立即在您的本地计算机上试用 Elastic。
我们开发人员很容易认为良好的自动完成功能是理所当然的。它就是有效 - 直到您尝试自己构建它。
这篇文章是关于我们最近为支持 ES|QL 的持续发展而进行的重新架构。
关于 ES|QL 系列
如果你还没听说过,ES|QL 是 Elastic 推出的新查询语言。它非常强大,我们认为它将成为未来 AI 代理、应用程序和人类与 Elastic 交互的主要方式。因此,我们在 Kibana 的多个地方(包括 Discover 和 Dashboard 应用)提供了 ES|QL 的编辑体验。
要理解这次重构,关键是要了解一些语言组件。
一个 ES|QL 查询由一系列连接在一起的命令组成,用于执行一连串的操作。
这里,我们将一个索引的数据与另一个索引进行连接:
FROM firewall_logs-* METADATA _index | LOOKUP JOIN threat_list ON source.IP | SORT _index
在上面的示例中,FROM、LOOKUP JOIN 和 SORT 是命令。
命令可以包含主要的子组件(称为子命令),通常由下一个管道符号前的第二个关键字标识(例如上面示例中的 METADATA)。和命令一样,子命令也有自己的语义规则,用于定义关键字后面可以出现的内容。
ES|QL 也有函数,看起来与你预期的一样。请看下面示例中的 AVG:
FROM logs-* | STATS AVG(bytes) BY agent.name
自动补全是帮助用户学习 ES|QL 的一个重要功能。
自动补全 1.0
我们最初构建的自动补全引擎具有以下几个关键特点:
- 声明式 - declarative —— 使用静态声明来描述命令
- 通用性 - generic —— 严重依赖通用逻辑,适用于大多数或全部语言上下文
- 具体化子命令 - Reified subcommands—— 将子命令视为一等抽象,拥有自己的逻辑
在顶层建议程序中,我们的代码会分析查询内容,检测用户光标所在的大致区域。然后根据语言子组件的不同,进入多个子程序中的一个。
命令和子命令的语义是通过 “命令签名 - command signature” 以声明式方式描述的。它定义了命令名称后可以使用的模式。比如,它可能会声明 “接受任意数量的布尔表达式”,或者“先接受一个字符串字段,再接受一个数值字面量”。
如果第一次分析判断光标处于某个命令或子命令中,对应的分支就会尝试将(子)命令签名与查询内容进行匹配,并以通用的方式推断出建议内容。
问题开始显现
起初,这种架构是有效的。早期的 ES|QL 命令相对统一。它们基本上看起来像这样:
COMMAND arg[, arg] SUB_COMMAND arg[, arg]
但随着时间的推移,命令开始变得更加定制化。
随着每个新命令的增加,几个问题也随之出现并不断加剧:
- 代码复杂性 —— 自动补全的代码变得庞大、复杂且难以理解。很难分清哪些逻辑适用于哪些命令。
- 缺乏正交性 —— 对语言某一部分行为的更改常常会影响到语言的其他部分。例如,在 KEEP 中的字段列表添加逗号建议,意外地也在 DISSECT 的字段后给出逗号建议 —— 这是无效的。
问题在于,新的语法和行为让我们原本 “通用” 的代码需要越来越多的特定命令分支,而命令定义则需要越来越多其实只适用于单个命令的 “通用” 设置。
逐渐地,我们开始意识到,用一个声明式接口来描述每个命令结构和行为的细微差异,这个想法有些理想化。
投资重构的时机
什么时候该投资进行重构?答案因情境而异。你需要权衡好收益与成本。说实话,你通常可以长期承担低效带来的代价 —— 而且这可能是合理的。
推迟重构的一种方式是 “治标不治本”。我们就是这样坚持了好几个月。我们用冗长的注释来应对代码复杂性,用更完善的测试覆盖率和细致的人工测试来应对正交性不足的问题。
但总有一个时刻,修修补补的代价超过了彻底重构的成本。对我们来说,这个节点就是一个出色的新 ES|QL 功能的引入 —— 基于聚合的过滤。
WHERE 命令自 ES|QL 初期就已经存在,但这个新功能让 WHERE 可以作为 STATS 中的子命令使用。
... | STATS COUNT(*) WHERE <expression>
这看起来像是一个小改动,但它打破了原本清晰区分命令与子命令的架构界限。现在,我们有了一个既是命令又可以作为子命令的结构。
这个基本抽象的突破,加上之前积累的各种低效问题,让我们决定是时候进行投资了。
Autocomplete 2.0
ES|QL 并不是一个通用语言,而是一种查询语言。所以我们决定接受一个现实:命令本就是为特定需求而设计的(符合传统查询语言的风格)。
新的架构必须足够灵活和适应性强,同时要清晰地表达出哪些代码属于哪个命令。这意味着我们需要一个具备以下特性的系统:
- 命令式 - Imperative —— 不再通过声明命令名之后允许的内容并单独解释声明,而是直接编写逻辑来验证命令的正确性。
- 命令专属 - Command-specific —— 每个命令都有自己的逻辑。不再存在适用于所有命令的通用处理程序。
在 Autocomplete 1.0 中,前期的分类逻辑承担了大量工作。现在,它只判断光标是否已经位于某个命令内部。如果在命令内,它就直接交给该命令专属的建议方法。现在大部分的处理逻辑都发生在具体命令内部,该命令拥有对其建议生成的完整控制权。
这并不意味着命令之间完全不共享逻辑。它们仍然会将建议的生成,甚至一些初步判断步骤,委托给可复用的子程序(例如判断光标是否位于一个 ES|QL 函数中)。但同时,它们保留了按需定制行为的灵活性。
为每个命令提供自己的建议方法提升了代码隔离性,减少了副作用,也更清晰地表达了哪些代码适用于哪个命令。
核心仍是用户
毫无疑问,这次重构为开发者带来了更好的体验。每个接触过两个系统的人都能感受到这种改变带来的清新感。但归根结底,我们进行这项投入是为了服务我们的用户。
首先,有些 ES|QL 功能若没有此次重构,是无法合理支持的。我们的用户在编写 ES|QL 时期待获得高质量的建议,现在我们可以在更多上下文中满足这一需求。
旧系统很容易引入回归问题。而现在,我们预计此类问题会更少。
我们团队最主要的任务之一就是为新命令添加支持。现在,我们可以更快完成这项工作。
虽然这项工作还没有结束,但我们已经建立起了一个支持变化、而非抵抗变化的系统。通过这次投入,我们为语言和编辑器的未来发展打下了坚实的基础。
原文:How we rebuilt autocomplete for ES|QL - Elasticsearch Labs

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
懒懒笔记 | 课代表带你梳理【RAG课程 9&10:大模型微调与思维链蒸馏】
在前面的教程中,我们通过优化检索器和召回策略,提升了RAG系统的检索精度。但要生成高质量的回复,大模型的能力同样关键。这就像烹饪,不仅需要优质食材(优化的检索模块),还需要优秀的厨师(强大的LLM)。 尽管掌握了基础,但在实际应用中,我们仍可能遇到问题: 🙋♂️“模型回复不够好,怎么办?” 🙋♂️“如何提升模型的理解和生成能力?” 光有大模型还不够,咱得让它更懂我们的业务、更贴地飞才行! 第 9、10 讲就是专门为此准备的——聚焦模型微调和知识蒸馏,让你的 RAG 系统既聪明又高效,真正从能用走向好用,稳稳拿捏复杂任务! 如何通过微调提升RAG系统的大模型能力? 影响RAG系统精度主要有两个因素:召回的效果+模型内容生成的能力 Why - 为什么做微调? 提升模型适应性:微调就像是给模型量身定制的“训练计划”,让模型在特定领域变得更加专业和强大。通过微调,模型能够更好地理解和处理特定领域的知识和任务。 增强生成能力:微调不仅提升模型的理解能力,还能增强其生成内容的质量和准确性。这对于需要高质量输出的应用场景尤为重要。 What - 微调是什么? 微调是通过在特定领域...
- 下一篇
校企联动 开源共创 东方通& openEuler Meetup开启开发者效率变革
5月27日,东方通与OpenAtom openEuler(简称"openEuler")社区联合主办的openEuler社区云原生开源中间件Meetup天津站在天津职业技术师范大学圆满落幕。此次活动以轻舟融合管理平台和云翼数据缓存中间件云原生管理平台两大开源项目为核心,聚焦云原生中间件技术实践与开发者赋能,通过技术分享、实战演示与openEuler开源实习计划发布,培养兼具创新思维与实践能力的技术人才,携手推动云原生中间件技术赋能研发效能提升。 校企联合 共促开源项目交流 天津职业技术师范大学信息技术工程学院教学副院长武志峰发表致辞,他表示,此次与东方通合作举办开源技术沙龙,旨在为学生提供接触实战技术的机会,帮助他们在实践中提升技能,培养具备实战能力的创新型人才。这种产教深度融合的模式,不仅能为学生职业发展奠定坚实基础,更能为国家科技自主创新输送“新鲜血液”。 东方通开发部经理王普在致辞中强调,基础软件是软件工程的核心组件,在数字化转型中发挥着关键作用,而开源是推动技术进步的重要方式。非常期待年轻开发者能积极参与到轻舟、云翼等开源中间件项目中来,这些项目不仅能帮助开发者提升开发效率,更...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8编译安装MySQL8.0.19
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2整合Redis,开启缓存,提高访问速度