首页
/ Understand-Anything 的 Rails 框架附加提示词(rails.md):如何让 LLM 精准解析 Rails 项目的知识图谱

Understand-Anything 的 Rails 框架附加提示词(rails.md):如何让 LLM 精准解析 Rails 项目的知识图谱

2026-09-06 15:01:05作者:温玫谨Lighthearted

本文以 Understand-Anything 插件中的 rails.md(Ruby on Rails Framework Addendum)为主体,完整解析这份"框架附加提示词"的设计意图与全部规则:标准文件角色映射表、四类 Rails 特有边的识别模式、七个架构层定义,以及应写入 languageLesson 的六个 Rails 标志性模式;并结合 框架注册表Rails 框架配置understand 技能主流程 的源码,说明这份文档在"检测 → 注入 → 分层"的完整调用链中如何生效。读完后,你能理解该项目对任意框架附加文档的通用扩展机制,并掌握为 Rails 项目生成可交互知识图谱时提示词背后的分层与连边逻辑。

1. rails.md 是什么:一份"条件注入"的框架附加提示词

rails.md 开头的两行注释定义了它的运行方式:

Injected into file-analyzer and architecture-analyzer prompts when Rails is detected. Do NOT use as a standalone prompt — always appended to the base prompt template.

也就是说,它不是独立提示词,而是一份"附加件(Addendum)":只有当 Understand-Anything 检测到目标项目使用 Rails 时,这份文档的全文才会被追加到 file-analyzerarchitecture-analyzer 两个子代理的基础提示词模板之后,为分析器叠加 Rails 专属的约定知识。这与 understand 技能主流程 中 Phase 4 的"框架附加注入"步骤一一对应:

  1. 使用 architecture-analyzer 代理定义 作为基础模板;
  2. 对 Phase 1 检测到的每种语言,读取 ./languages/<language-id>.md 并追加到 ## Language Context 标题下;
  3. 对每个检测到的框架,读取 ./frameworks/<framework-id-lowercase>.md(例如 ./frameworks/rails.md),将其全文追加在语言上下文之后;若对应文件不存在则静默跳过;
  4. 若输出语言非英文,再追加 ./locales/<language-code>.md 作为 ## Output Language Guidelines

最终分发给子代理的提示词中还会附带"Frameworks detected"清单与两级目录树,并明确要求"用目录结构、语言上下文和框架附加件(即上面追加的内容)来指导分层判断,目录结构是层边界的强证据"(见 SKILL.md)。因此 rails.md 的四个章节——文件角色、边模式、架构层、语言模式——分别精确命中了分析器需要决策的四个环节:打标签、连边、分层、生成教学性说明

2. 何时触发注入:Rails 的自动检测机制

附加件能否被注入,取决于框架检测是否命中。Rails 的机器可读配置定义在 rails.ts

export const railsConfig = {
  id: "rails",
  displayName: "Ruby on Rails",
  languages: ["ruby"],
  detectionKeywords: [
    "rails",
    "railties",
    "actionpack",
    "activerecord",
    "actionview",
  ],
  manifestFiles: ["Gemfile"],
  promptSnippetPath: "./frameworks/rails.md",
  entryPoints: ["config.ru", "bin/rails"],
  layerHints: {
    controllers: "api",
    models: "data",
    views: "ui",
    helpers: "utility",
    mailers: "service",
    jobs: "service",
    channels: "service",
    middleware: "middleware",
    lib: "service",
  },
} satisfies FrameworkConfig;

各字段与本文档的对应关系如下:

字段 取值 作用
id / displayName rails / Ruby on Rails 检测结果的标识;id 小写化后即附加件文件名的来源(frameworks/rails.md
languages ["ruby"] 按语言维度查询框架时命中的语言
detectionKeywords railsrailtiesactionpackactiverecordactionview 在清单文件内容中做(小写化后的)子串匹配
manifestFiles ["Gemfile"] 只检查名为 Gemfile 的清单文件
promptSnippetPath ./frameworks/rails.md 指向本附加件,register() 时经 Zod schema 强制非空
entryPoints config.rubin/rails 项目入口点提示,与 rails.md 中 config.ruentry-point 标签互相印证
layerHints 目录名 → 层 id 与 rails.md 的"架构层"表保持一致(如 controllers → apimodels → data

检测逻辑实现在 FrameworkRegistry.detectFrameworks:遍历已注册框架的每个 manifestFiles 条目,先按文件名(basename 或 */<文件名> 结尾)在扫描到的清单内容中找到 Gemfile,再把其内容整体小写化,只要命中任意一个 detectionKeywords 就登记该框架。由于 railtiesactionpackactiverecordactionview 都是 Rails 组件 gem,即使 Gemfile 里没直接写 rails,只要引入了其中任一核心组件也会被识别——这是比单纯匹配 gem 名更鲁棒的检测策略。

配置结构本身由 FrameworkConfigSchema 用 Zod 校验:languagesdetectionKeywordsmanifestFilespromptSnippetPath 均为必填且非空,entryPointslayerHints 可选。config-schema.test.ts 还断言"每一个内建框架都必须有非空的 promptSnippetPath",即附加件路径是每个框架配置不可省略的一环。Rails 配置经由 builtinFrameworkConfigs 注册(当前共 10 个内建框架:Django、FastAPI、Flask、React、Next.js、Express、Vue、Spring、Rails、Gin),并由 FrameworkRegistry.createDefault() 预填充。

在技能主流程中,Phase 1 的 project-scanner 会产出 scan-result.json(包含 languagesframeworks 清单),Phase 4 才据此执行上面第 3 步的附加件注入——检测与注入分属不同阶段,但通过 scan-result.json 中的框架列表衔接。最终 knowledge-graph.jsonproject.frameworks 字段也会记录这次检测结果(见 SKILL.md 输出格式)。

3. Canonical File Roles:Rails 标准文件角色与标签映射

rails.md 的第一张表告诉分析器:在 Rails 项目中,"看到什么路径,就该打什么角色标签"。这张表是 LLM 打标签的确定性依据,完整继承如下:

File / Pattern Role Tags
config.ru Rack entry point — boots the Rails application for the web server entry-point
config/application.rb Application configuration — sets up Rails, loads gems, configures middleware entry-point, config
app/controllers/*_controller.rb Controllers — handle HTTP requests, orchestrate models, render responses api-handler
app/controllers/concerns/*.rb Controller concerns — shared controller behavior via mixins middleware, utility
app/models/*.rb ActiveRecord models — map to database tables, contain validations and associations data-model
app/models/concerns/*.rb Model concerns — shared model behavior via mixins utility
app/views/**/*.erb, app/views/**/*.haml View templates — HTML rendering with embedded Ruby ui
app/helpers/*_helper.rb View helpers — utility methods available in templates utility
app/mailers/*_mailer.rb Action Mailer classes — send email notifications service
app/jobs/*_job.rb Active Job classes — background job processing service
app/channels/*_channel.rb Action Cable channels — WebSocket communication service
app/serializers/*_serializer.rb API serializers — JSON response formatting (ActiveModelSerializers, Blueprinter) api-handler, utility
app/services/*.rb Service objects — encapsulate complex business logic service
db/migrate/*.rb Database migrations — schema changes versioned by timestamp config, data-model
db/schema.rb, db/structure.sql Generated schema snapshot — current database structure data-model, config
config/routes.rb Route definitions — maps URLs to controller actions routing, config
config/initializers/*.rb Initializers — run once at boot to configure gems and services config
lib/**/*.rb Library code — custom classes, Rake tasks, extensions utility, service
spec/**/*_spec.rb, test/**/*_test.rb RSpec or Minitest test files test

这些标签不是任意词汇:file-analyzer 代理 的提示词本身就给出了标签词表(entry-pointapi-handlerdata-modelservicetestutility 等),并要求"3-5 个短横线连接的小写标签",其中还明确写着"文件名为 config.ru 的按 entry-point 处理(Ruby Rack 服务器)"。也就是说,rails.md 的角色表是 file-analyzer 通用规则之上的 Rails 特化补充,两者标签体系完全一致。

几个值得注意的映射细节:

  • config.ruconfig/application.rb 都带 entry-point:前者是 Rack 启动入口,后者是应用装配入口(加载 gems、配置中间件),这与 rails.tsentryPoints: ["config.ru", "bin/rails"] 的声明相互呼应。
  • concerns 目录的标签差异app/controllers/concerns/ 标为 middleware, utility(共享控制器行为,近似中间件),而 app/models/concerns/ 只标 utility——同一个 ActiveSupport::Concern 机制,因所在目录不同而角色定位不同。
  • 迁移与 schema 的双标签db/migrate/*.rbconfig + data-modeldb/schema.rbdata-model + config,说明它们既是数据模型描述、又是可执行/可生成的配置产物,这一双重身份在后文的边模式中会再次体现。
  • lib/** 同时标 utilityservice:库代码可能承载通用工具,也可能封装业务逻辑,标签留双选项由分析器按文件摘要判断。

4. Edge Patterns:Rails 特有的四类图边识别规则

知识图谱的价值一半在节点、一半在边。rails.md 的"Edge Patterns to Look For"章节给出了四条 Rails 特有的连边规则,每条都指定了边类型(对应 file-analyzer 边类型表 中受支持的类型):

1)Route-to-controller mapping(路由→控制器)config/routes.rb 定义了 resources :usersget '/foo', to: 'bar#baz' 时,从路由文件指向对应控制器创建 configures 边。RESTful 资源(resources :x)会生成一整套 action 映射(index/show/new/create/edit/update/destroy),因此单条路由声明可展开为多条映射关系。configures 在 file-analyzer 的边类型表中权重为 0.6,方向 forward,语义是"配置/声明文件影响代码文件"——config/routes.rb 正是声明 URL 到控制器动作映射的配置文件。

2)ActiveRecord associations(模型间关联) 当模型定义了 has_manybelongs_tohas_onehas_and_belongs_to_many 时,在两个模型文件之间创建 depends_on 边,且边的描述必须标明关联类型与方向(例如 "User has_many Posts")。depends_on 在边类型表中同样权重 0.6,语义是"比 imports 更宽的运行时依赖"——Ruby 模型间往往没有显式 require 关系(Active Record 通过命名约定自动关联),所以这里不产生 imports 边,而由语义分析补出 depends_on 边。

3)Controller-to-model(控制器→模型) 当控制器调用模型方法(User.find@post.save)时,从控制器指向模型创建 depends_on 边。文档特别强调"控制器是模型数据的主要消费者",这条规则刻画了 Rails MVC 中数据流向的主干:routes.rb →(configures)→ controllers →(depends_on)→ models →(depends_on)→ models

4)Callbacks(回调) 当模型或控制器使用 before_actionafter_savebefore_validation 等回调时,应把它们记录为类中间件(middleware-like)边。文档给出的理由是:回调构成了从调用点看不见的隐式执行路径——before_action :authenticate_user! 的实际执行发生在每个动作之前,静态调用图里找不到这条边,若不显式建模,知识图谱就会丢失关键的执行顺序信息。

这四类规则与 architecture-analyzer 的 Phase 1 结构脚本形成互补:脚本负责确定性地计算导入邻接、组间依赖方向(routes → services 一类的 interGroupImports),而 rails.md 负责教 LLM 识别那些"导入图里不存在、必须靠语义才能发现"的 Rails 边。

5. Architectural Layers:Rails 项目的七个标准架构层

rails.md 的第三张表规定了"检测到 Rails 时,节点应如何落到层上"。层 id 采用 layer:<kebab-case> 格式,与 architecture-analyzer 的 Layer ID Formatlayer:apilayer:datalayer:uilayer:middlewarelayer:utilitylayer:configlayer:test)逐项吻合。完整继承如下:

Layer ID Layer Name What Goes Here
layer:api API Layer app/controllers/app/serializers/、API-specific controllers
layer:data Data Layer app/models/db/migrate/db/schema.rb
layer:ui UI Layer app/views/app/helpers/app/assets/app/javascript/
layer:service Service Layer app/mailers/app/jobs/app/channels/app/services/lib/
layer:config Config Layer config/routes.rbconfig/initializers/config/application.rbconfig.ru
layer:middleware Middleware Layer app/middleware/、controller concerns、Rack middleware
layer:test Test Layer spec/test/*.spec.rb*_test.rb

这张表与 rails.ts 的 layerHints 保持同一套目录→层的映射(controllers→apimodels→dataviews→uihelpers→utilitymailers/jobs/channels/lib→servicemiddleware→middleware),一处面向 LLM 提示词、一处面向程序化查询(getForLanguage/getById),双轨一致。它也与 architecture-analyzer 的目录模式表 对齐:mailersjobschannels 被归类为 serviceconfig.ru 被识别为 entryGemfile 被识别为 config——因此即便 LLM 忽略附加件,确定性脚本层也有兜底的 Rails 目录识别能力。

分层约束由 architecture-analyzer 的基础提示词给出,rails.md 不重复这些约束而是直接给出"答案表":3-10 个层、每个文件节点必须且只能落入一个层的 nodeIds、层 description 必须针对当前项目定制而非通用套话。对 Rails 项目而言,这意味着标准产出通常是上表七层(小项目可合并,例如把 middleware 并入 api、把 config 并入项目根层)。

6. languageLesson:应写入知识图谱的六个 Rails 标志性模式

rails.md 最后一章"Notable Patterns to Capture in languageLesson"列出六个应沉淀进图谱教学内容的 Rails 模式。languageLesson 是 understand 流程中面向"读者/新人"的教育性字段(file-analyzer 节点上有可选的 languageNotes,最终图谱在更高层面汇总语言级 lesson),其目的是让知识图谱不只是结构图,而是"会教人的图"(项目口号:Graphs that teach > graphs that impress)。六条完整内容如下:

  • Convention over configuration(约定优于配置):Rails 从命名约定推导路由、表名和文件位置——UsersController 对应 users_controller.rb,处理 /users 路径,查询 users 表。理解这一点后,很多"看不见的关联"(比如控制器和模型的绑定不需要显式声明)就不成谜。
  • ActiveRecord pattern:模型是数据库的包装器——每个模型类映射一张表,实例映射行,属性映射列,且带自动类型转换。这是 layer:data 中模型文件语义的核心。
  • Concerns for shared behaviorActiveSupport::Concern 模块以 mixin 方式被模型或控制器 include,跨类共享验证、scopes、回调与方法。这解释了 app/models/concerns/app/controllers/concerns/ 目录的存在意义,也与第 4 节中 concerns 的标签映射(middleware/utility)呼应。
  • Strong parameters for mass-assignment protectionparams.require(:user).permit(:name, :email) 以白名单方式声明哪些字段可被用户输入写入——控制器必须显式声明可赋值属性。这是 Rails 安全模型的关键,理解它才能读懂控制器里 permit 调用的意图。
  • RESTful resource routingresources :posts 生成 7 条标准 CRUD 路由;Rails 强烈倾向 RESTful 设计,每个控制器对应一个资源。这直接支撑第 4 节中"RESTful 资源展开为整套 action 映射"的连边规则。
  • Callbacks and observersbefore_saveafter_create 等回调把逻辑注入对象生命周期,形成难以追踪的隐形执行路径——与第 4 节"回调要记为类中间件边"的规则形成原理呼应:正因为回调路径在静态视图里不可见,才需要显式建模并写入 lesson。

7. 全链路总结:一份 Markdown 如何进入知识图谱

把本文各节串起来,rails.md 在 Understand-Anything 中的完整生命周期是:

  1. 检测:project-scanner 读取 Gemfile 内容,FrameworkRegistry.detectFrameworks 用小写关键词匹配命中 rails 配置,scan-result.json 记录 frameworks: ["rails"]
  2. 注入:Phase 4 按 frameworks/rails.md 读取本附加件全文,追加到 architecture-analyzer 基础提示词的语言上下文之后(SKILL.md);file-analyzer 侧同样在使用本附加件时获得同套 Rails 规则;
  3. 应用:分析器依据第 3 节角色表打标签(entry-point/api-handler/data-model 等)、依据第 4 节边模式连边(configures/depends_on 及回调类中间件边)、依据第 5 节七层表输出 layer:api 等层划分并保证每个文件节点恰好归入一层、依据第 6 节生成 languageLesson 教学内容;
  4. 落盘:最终 knowledge-graph.jsonproject.frameworks 中记录检测到的 Rails,节点与边携带上述标签与分层信息,供交互式 dashboard 渲染与检索。

从工程视角看,这套机制的扩展性值得注意:新增一个框架 = 写一份 frameworks/<id>.md 附加件 + 在 frameworks/index.ts 注册一个通过 FrameworkConfigSchema 校验的配置对象(promptSnippetPath 必须指向该附加件,空值会被测试 config-schema.test.ts 明确拒绝)。rails.md 本身就是这一契约的现成范本:它不重写基础提示词,只在"文件角色、边模式、分层、语言模式"四个决策点上做最小而完整的增量,恰好覆盖了 LLM 分析 Rails 代码库时最容易出错的四类判断。

登录后查看全文
热门项目推荐
相关项目推荐