Shire 设计原则

原则 1:IDE 即上下文环境

集成开发环境(IDE)不仅仅是一个文本编辑器或编程环境,它更是一个能够理解、处理和操作代码的高级工具。这种设计理念下,IDE 的作用远不止于代码编辑,它还包括了代码的语法分析、语义理解以及操作执行等功能。 在 Shire 中,我们采纳了一系列的设计原则,以支持 IDE 的智能化和自动化:

  • 上下文感知变量化。我们定义了一系列上下文变量,例如选中的文本、光标前后的文本、文件名和路径等。这些变量能够辅助 IDE 理解和操作代码的不同部分,使得开发者与 AI 都能基于上下文信息进行代码处理和分析。
  • 模式-动作上下文构建。我们借鉴 Unix 的 Shell 编程思想,引入了模式-动作概念。这种模式允许根据特定的模式(如文件类型或内容特征)执行相应的动作(如 find、sort、xargs)。通过此模式,IDE 可以根据用户定义的条件对文件和数据进行筛选和处理,显著提升了代码操作的灵活性和效率。
  • 查询语言 ShireQL。这是一种用于描述和执行 PSI(程序结构接口)查询的语言。DSL(特定领域语言)定义了变量声明、条件查询和结果选择的结构。这种语言使得开发者和 AI 能够根据特定的语法结构和查询条件,从代码中提取和分析所需信息。这样的设计让 IDE 不仅仅是一个静态的文本编辑器,而是一个能够通过语义理解和查询执行来智能操作代码的工具。

示例:

解释如下代码片段。

项目相关的技术栈上下文: $frameworkContext

$selection

在此示例中,我们展示了如何利用 Shire 的设计原则和功能来解析代码和上下文信息。通过定义变量和执行特定的模式-动作操作,IDE 可以根据条件筛选和处理代码文件,并通过 PSI 查询语言进行高级的代码结构分析和提取。这样的能力不仅提升了开发者的效率,还使得 AI 能够更智能地参与到代码开发和分析过程中。

原则 2:语言即抽象接口

语言接口是一种使用自然语言作为领域特定语言(DSL)或与系统进行交互的接口。它通过解析、处理和分析自然语言,指导系统的设计、开发和执行。 其设计目的是提高开发效率、准确性和用户体验,使用户能够使用自然语言描述系统需求、执行任务并获取系统生成的结果。

在 Shire 中,我们采纳了一种语言接口设计原则,将自然语言作为领域特定语言(DSL)或与系统进行交互的接口。这种设计原则涵盖以下几个方面:

  • 领域特定语言(DSL)。DSL 是一种专门用于解决特定领域问题的语言,其通过简单、直观的语法和语义,让开发者更容易地描述和执行特定任务。在 Shire 中,我们引入了一种类似于 YAML 的 HobbitHole,用于描述数据处理流程和 IDE 交互逻辑。通过这种 DSL,开发者可以定义数据处理流程、交互逻辑和输出结果。
  • 自然语言即 LLM 接口。对于大型语言模型(LLM)而言,自然语言是一种重要的接口,用于描述和执行代码生成任务。开发者可以通过自然语言描述, 定义代码生成模板、变量和条件,以及执行代码生成任务。这种设计原则让开发者能够更直观、灵活地描述和执行代码生成任务,提升了代码生成的效率和准确性。 示例:
---
name: "AutoTest"
description: "AutoTest"
interaction: AppendCursor
actionLocation: ContextMenu
---

为以下的 ${context.language} 代码编写单元测试。
...

通过上述配置,我们定义了一个名为 “AutoTest” 的 HobbitHole,用于生成自动化测试代码。通过这种 DSL + 自然语言的结合,我们可以定义 IDE 中的交互类型、操作位置和其他属性,进而实现代码生成任务的自动化和智能化。

原则 3:原子功能单元(Atomic Functional Units)

原子功能单元(Atomic Functional Units, AFUs)是一种设计方法,旨在将复杂系统分解为独立且功能明确的最小操作单元。这种设计原则受到 Linux 设计思想的启发,强调模块化、独立性和简洁性。

  1. 原子性和模块化。每个原子功能单元(AFU)都是独立且不可再分割的基本操作单元,采用模块化设计,能够独立执行特定任务,并可以自由组合和重用。
  2. 简单接口与管道式处理。AFUs 暴露简单明确的输入和输出接口,通过管道连接,形成高效且连贯的数据处理流程,隐藏内部实现细节,简化用户操作。
  3. 高内聚低耦合。每个 AFU 内部专注于特定任务(高内聚),与其他单元通过简单接口进行通信(低耦合),提升系统的灵活性、可维护性和扩展性。

以下是一个示例,展示如何对Java文件进行Embedding,以提供模板中的变量,作为LLM(大型语言模型)的上下文:

---
variables:
  "searchResult": /*.docx/ { splitting | embedding | searching("API 设计范式") }
---

根据如下的内容,总结一下 API 如何设计:

$searchResult

在这个示例中:

  • splitting:将文档拆分为独立的部分,每个部分可以单独处理。
  • embedding:对每个部分进行 Embedding,以便在 LLM 中使用。
  • searching:在 Embedding 的内容中搜索特定的关键词或概念。

通过这种方式,我们可以将复杂的任务分解为独立的原子功能单元,每个单元都是独立的,可以自由组合和重用,从而提高系统的灵活性和可维护性。