RAG + 语义标记
阅读其他语言: English Español 한국어 Português
文档在不同的软件项目中的重要性各不相同, 但即使是最重要的文档也具有固有的辅助角色。 它并非程序依赖于正确运行的东西。 即使文档与程序共享数据,连接仍然是单向的。 面向用户的文档反映了产品,并不改变产品的工作方式。
这主要是出于技术原因。 如果自然语言的指令能够足够具体, 并且计算机在解读这些指令时表现出色,我们就可以通过编写文档来实现新功能和修复错误。 这听起来很熟悉,不是吗?
尽管人们还在争论是否可能完全用自然语言进行编程, 但这种潜在的变化实际上更多的是关于软件开发的可访问性,而不是引入一些新的程序操作方式。 最终,我们将得到相同的二进制文件,现在只是多了一个值得赞赏的编译器。
AI能否以不同的方式驱动特性呢? 今天,我想介绍一下最近在 JetBrains IDEs中的一项AI驱动特性, 它直接利用了自然语言处理,将大量的我们的文档变成了一个极其有用的开发资产。
动作搜索
从2024.3版本开始,JetBrains IDEs中的AI助手可以访问IDE动作,并帮助你找到解决问题的正确动作。 另外,它还可以为你执行这个动作:
正如前面所述,这个特性是由文档驱动的。 虽然古老的代码肯定起到了一部分作用,但选择正确动作完全依赖于 RAG (检索增强生成)的高级形式 – 不需要大量的LLM函数或特别的映射。
在深入细节之前,让我们简单回顾一下RAG的概念。
RAG
检索增强生成(RAG) 是一种常用的技术,用于提高LLM响应的准确性和地面性。 当LLMs需要对超越他们的训练数据和频繁变化的事实给出回应时,这种技术尤其有效,这使得微调变得不切实际。
在最常见的形式中,这种技术包括在文档上维护一个索引。 在这个索引中,键反映了文档元素的意义, 由embeddings表示, 值对应于元素的内容或对元素本身的引用。 得益于键的数值表示,相应的 元素可以使用余弦相似性或 k-最近邻(KNN)等方法语义地比较和检索。
当你在一个由RAG辅助的AI聊天中提问某个问题时,会发生什么:
我怎么更改字体大小?
系统首先搜索索引,如果成功的话, 附加到提示上。 例如:
我怎么更改字体大小?
这里是一些可能帮助你回答问题的补充信息:
-> 搜索结果被插入到这里 <-
使用这种方法,可以从提供的补充信息中推断出正确的答案, 使LLM的回应更有根据和准确。 从最终用户的角度看, 这可能会让人觉得模型变得更聪明了,而实际上模型并没有改变 — 唯一的区别在于提示。
现在让我们看看我们如何可以增强这个方法。
语义标记
如果你编写技术文档, 你可能已经熟悉了 语义标记的概念:
使用语义标记,你可以为每个元素指定其 “含义”
例如,Markdown就不是语义的。 在Markdown中,你操作的是常见的文档元素,如标题,段落,列表等,除了一些排版属性。 这个语法概述了一个高级的结构,并告诉处理器如何渲染文档。 但它没有告诉你文档中各种元素的目的,或者意思是什么。
这里有一个简短的例子。星号表示处理器应该将这个短语斜体化,类似于在HTML中的 <i>
的作用:
*在过马路前看两边!*
相反,MDX,Markdown的一个超集,具有语义属性。 MDX允许你定义自定义元素,这些元素通常代表UI组件,并可以传达内容的预期目的:
<Warning>
在过马路前看两边!
</Warning>
与原生Markdown不同,这个特定的MDX例子抽象了视觉方面,更侧重于内容的目的。
作为文档编写人员,我们并不太关心 <Warning>
是否应使用斜体或以其他方式从常规文本中突出出来。
它的样式在另一个地方定义,如组件本身或CSS样式表中。
这样的关注点分离使代码库更易于维护,并让你根据内容的含义以集中的方式更改样式。
完美的匹配?
在 JetBrains,我们使用 Writerside编写我们的文档。 这个工具支持Markdown和语义XML作为文档的源格式。 下面的例子显示了一个使用Writerside的语义XML写的典型的文档结构:
<chapter title="Testing" id="testing">
... some content ...
<procedure title="Navigate to tests" type="choices">
<p>
When at a symbol declaration, you can navigate to the corresponding
tests by doing one of the following:
</p>
<step>
From the main menu, select <ui-path>Navigate | Test</ui-path>.
</step>
<step>
Press <shortcut key="GotoTest"/>.
</step>
</procedure>
... more content ...
</chapter>
你会注意到在提供的片段中有一些元信息。 它已经对于上述原因具有价值, 但没有什么能阻止我们将它用于一些额外的用途。
考虑到 <shortcut>
标签,
该标签表示一个与平台相关的键绑定。
这个标签是一个间接层的一部分,允许
以集中的方式管理和验证快捷键的提及。
要在文档中插入一个快捷键,你使用 <shortcut>
标签
和对应的动作ID,就像这样: <shortcut key="CoolAction">
。
在构建过程中,工具验证并将 <shortcut>
元素
转化为可用键映射的实际键绑定。
这种方法使文档和产品之间的快捷键同步,并为文档用户提供了选择他们喜欢的键映射的灵活性。 为了看到这个在实践中的样子, 访问IntelliJ IDEA帮助 并注意文本中的快捷键是如何根据在Shortcuts菜单中选择的键映射发生变化的:
这就是 <shortcut>
标签的主要目的。
这个标签在增强RAG方面有什么好处呢?
最直接的用途是在AI聊天中显示平台特定的快捷键, 就像在帮助页面上一样:
然而,更有趣的部分是,类似于建立用于检索事实和指令的索引, 我们可以建立能够查找动作ID的索引。
在之前讨论的简单RAG场景中,我们从用于检索的同一元素生成了嵌入。 然而,对于动作ID索引,我们将使用以下结构:
- 键是从包含
<shortcut>
标签的元素中派生出的嵌入 - 值是对应
<shortcut>
标签中的动作ID
在例子中,对于 <shortcut key="GotoTest"/>
的包含元素,将是 <step>
甚至整个 <procedure>
:
<procedure title="Navigate to tests" type="choices">
<p>
When at a symbol declaration, you can navigate to the corresponding
tests by doing one of the following:
</p>
<step>
From the main menu, select <ui-path>Navigate | Test</ui-path>.
</step>
<step>
Press <shortcut key="GotoTest"/>.
</step>
</procedure>
上下文很重要
为了展示索引包含元素内容重要性的例子,让我们以 IntelliJ IDEA 的 Set Value 特性为例。 这个特性让你在调试模式中程序挂起时更新变量。
对应的动作ID是 SetValue
。
然而,这个ID本身并没有多大的描述性。
考虑到 SetValue
和许多其他ID在编程中都是相当通用的词组,
单独基于这些ID的语义搜索将会产生大量的误报和漏报。
如果不在索引中包括额外的上下文,任务实际上是不可能的。
相反,通过建立动作ID和 surrounding 内容之间的关系,我们为AI助手提供了关于各个功能、其常见用例和限制的详细信息。 这些信息大大提高了检索的准确性:
客户端部分
最后,一旦AI助手有了正确的动作ID,它就可以建议这个动作,并且甚至可以显示一个按钮来从聊天中调用它:
当然,这个部分比简单地在UI中添加一个按钮要复杂一些。 考虑到IDE动作是取决于上下文的,有一些额外的检查需要实现, 但这个话题是非常特定于IntelliJ平台开发的,并且值得单独讨论。
其他标记元素
在这篇文章中,我们主要关注’动作搜索’特性,它通过从Writerside的 <shortcut>
标签中检索动作ID来工作。
然而,你可以将相同的原则应用到语义标记中的许多其他元素类型。
只是一个快速例子使用 <ui-path>元素。 这个元素表示一系列的UI元素,如菜单项, 用户需要通过这些元素来访问描述的功能。
<step>
Open the IDE settings (<shortcut key="ShowSettings"/>),
then navigate to <ui-path>Tools | Terminal</ui-path>.
</step>
在Web帮助中提供长路径是合理的,因为从网页直接导航到产品通常是不切实际的。 另一方面,当用户在产品中询问这个问题时,没有理由不直接显示对应的设置页面:
总结
不久前,许多人设想了 Web 3.0的概念。 他们的想法是将整个网络转移到语义标记, 以便机器可以像人一样使用它。 虽然这没有发生,但令人感兴趣的是同样的想法如何再次变得相关, 现在是从现代工具和技术的角度看问题。
我在这篇文章中讨论的特性只是你可以利用 你现有的良好实践,如语义标记,与Gen AI系统的一个例子。 还有更多的方法可以探索。 如果你对RAG特别感兴趣,这里有一份关于检索增强生成的精彩 教程集合。
你喜欢这篇文章吗?你喜欢尝试Gen AI吗? 即使我的博客没有评论部分,我仍然会很高兴 听到你的观点和用例, 所以不要犹豫使用页脚中的联系方式告诉我。
我们很快再见!