教程

生成架构图

使用 IBM Bob 分析 Galaxium Travels 代码库,并生成 Mermaid UML 类图、序列图和用例图。学习如何在 Ask 模式下使用上下文提及来探索代码,以及如何使用 Agent 模式将结果保存到代码仓库。

架构图能在你修改代码库之前,为团队提供一种共同的可视化语言。在本教程中,你将使用 Bob 读取 Galaxium Travels 的源文件,并生成三种类型的 UML 图:UML 类图、序列图和用例图。你将使用 Ask 模式安全地探索代码并生成图表标记,图表标记使用 Mermaid 格式。然后切换到 Agent 模式,将图表保存到项目中。

GitHub 原生支持在 Markdown 文件中渲染 Mermaid 图表,因此你可以将生成的图表保存为 .md 文件,并在 GitHub 上查看渲染效果。

在本教程中,Bob 的输出结果可能因代码库的当前状态而与示例有所不同。请将生成的标记作为起点,并根据需要进行调整。

学习要点

  • 上下文提及(Context mentions):在提示词中使用 @ 符号引用特定文件和文件夹。上下文提及让 Bob 明确知道需要分析哪些文件,从而生成更准确的图表。
  • Ask 模式:在不修改任何文件的情况下读取和分析代码。
  • Agent 模式:让 Bob 自主写入文件,将生成的内容持久化到项目中。

前提条件

完成本教程,你需要以下内容:

  • 已安装 Bob IDE
  • 本地已安装 Git,以便克隆 Galaxium Travels 示例仓库。
  • 熟悉 Bob 的基本使用方法。如果你是 Bob 的新用户,请先阅读快速入门教程

设置工作区

克隆 Galaxium Travels 仓库

在终端中运行以下命令,克隆 Galaxium Travels 示例仓库:

git clone https://github.com/ibm/galaxium-travels.git

启动 IBM Bob

在你的计算机上启动 IBM Bob IDE。

打开示例项目

在 Bob IDE 中,打开你克隆的 galaxium-travels 文件夹。如果 Bob 询问"您是否信任该文件夹中文件的作者?",请点击是,我信任作者

查看根目录中的 README.md 文件,了解应用程序及其架构概览。Galaxium Travels 应用模拟了一个航班预订系统,包含 React 前端、Python FastAPI 后端以及 Java 库存占位服务。该代码库具有一定的复杂性,能够代表真实世界的应用场景,因此非常适合用来生成架构图。

打开 Bob 聊天界面

如果聊天界面尚未打开,请点击导航栏中的 Bob 图标,或使用快捷键 Option + Command + B(Mac)或 Ctrl + Alt + B(Windows)。

初始化项目上下文

Bob 启动时默认进入 Agent 模式。如果你已切换了模式,请在运行初始化命令前先切换回 Agent 模式——Bob 需要写入文件来设置项目上下文。

在聊天界面输入框中输入 /init 命令。如果你禁用了自动审批,Bob 会请求你的权限来读取文件并写入 AGENTS.md 文件。

 /init

Bob 会读取项目中的相关文件,然后在根目录生成主 AGENTS.md 文件,同时创建一个 .bob 文件夹,其中包含每种模式对应的 AGENTS.md

查看生成的 AGENTS.md 文件,了解 Bob 如何设置项目上下文,以及 Bob 在各模式下具备哪些能力。

切换到 Ask 模式

在聊天输入框下方的模式选择器中选择 Ask,或在聊天输入框中输入 /ask 来切换模式。

与 Agent 模式不同,Ask 模式是只读的。Bob 可以读取和分析文件,但无法创建或修改任何内容,因此非常适合用于代码探索。

生成 UML 类图

UML 类图描绘了应用程序的数据模型:实体(类)、它们的属性,以及它们之间的关系。对于 Galaxium Travels,这涵盖了后端的 Python SQLAlchemy 模型和库存占位服务中的 Java 领域类。

编写一个提示词,分析两个服务的数据模型,并生成 Mermaid classDiagram。使用上下文提及来指定 Bob 需要分析的相关文件。默认情况下,Bob 会将 Mermaid 图表渲染为图片。若要查看原始 Mermaid 标记,请在提示词中加入"Output only the Mermaid code block. Do not render the Mermaid diagram."这条说明。

在 Ask 模式下,在聊天输入框中输入以下提示词:

Analyze the data models in @booking_system_backend/models.py and the 
Java domain classes in @booking_system_inventory_hold_service/src/main/java/com/galaxium/holdservice/domain.

Generate a Mermaid classDiagram that shows all classes, their attributes,
their methods (if any), and the relationships between them. 
Include the BookingStatus enum.

Output the Mermaid markup. Do not render the Mermaid diagram.

Bob 读取两个文件后,会生成类似以下内容的图表标记:

classDiagram
    direction LR

    %% ── Python / SQLAlchemy (booking_system_backend/models.py) ──────────

    class User {
        +int user_id PK
        +str name
        +str email
    }

    class Flight {
        +int flight_id PK
        +str origin
        +str destination
        +str departure_time
        +str arrival_time
        +int base_price
        +int economy_seats_available
        +int business_seats_available
        +int galaxium_seats_available
    }

    class Booking {
        +int booking_id PK
        +int user_id FK
        +int flight_id FK
        +str status
        +str booking_time
        +str seat_class
        +int price_paid
    }

    class BookingStatus {
        <<enumeration>>
        BOOKED = "booked"
        CANCELLED = "cancelled"
        CANCELED = "cancelled"
        COMPLETED = "completed"
    }

    %% ── Java / JPA (holdservice/domain) ────────────────────────────────

    class Quote {
        +String quoteId PK
        +Integer flightId
        +String seatClass
        +Integer quantity
        +Integer travelerId
        +String travelerName
        +Long pricePerSeat
        +Long totalPrice
        +Instant expiresAt
        +QuoteStatus status
        +Instant createdAt
        #onCreate() void
    }

    class QuoteStatus {
        <<enumeration>>
        CREATED
    }

    class Hold {
        +String holdId PK
        +String quoteId FK
        +HoldStatus status
        +Instant reservedUntil
        +String externalBookingReference
        +String errorMessage
        +Instant createdAt
        +Instant updatedAt
        #onCreate() void
        #onUpdate() void
    }

    class HoldStatus {
        <<enumeration>>
        HELD
        EXPIRED
        CONFIRMED
        RELEASED
        CONFIRMATION_FAILED
    }

    class AuditEvent {
        +String eventId PK
        +String entityType
        +String entityId
        +String eventType
        +String details
        +Instant createdAt
        #onCreate() void
    }

    %% ── Relationships ───────────────────────────────────────────────────

    User        "1" --> "0..*" Booking      : places
    Flight      "1" --> "0..*" Booking      : booked on
    Booking          ..>        BookingStatus : status

    Quote       "1" --> "0..*" Hold         : generates
    Quote            ..>        QuoteStatus  : status
    Hold             ..>        HoldStatus   : status

    AuditEvent       ..>        Quote        : references entityId
    AuditEvent       ..>        Hold         : references entityId

生成序列图

序列图按时间顺序展示组件在特定流程中的运行时交互方式。Galaxium Travels 的预订流程跨越了 React 前端、Python FastAPI 后端和 Java 库存占位服务。

编写一个提示词,追踪完整的预订流程并生成 Mermaid sequenceDiagram。使用上下文提及来指定 Bob 需要分析的相关文件。你在提示词中越具体地说明要分析哪些文件以及要绘制哪个流程,输出结果就越准确。

在 Ask 模式下,在聊天输入框中输入以下提示词:

Analyze the booking flow across @booking_system_frontend/src/services,
@booking_system_backend/server.py, @booking_system_backend/services/booking.py,
and @booking_system_inventory_hold_service/src/main/java/com/galaxium/holdservice/api.

Generate a Mermaid sequenceDiagram showing the complete flow for a
user booking a flight, including the quote and hold steps with the Java service.

Output the Mermaid markup. Do not render the Mermaid diagram.

Bob 追踪交互链后,会生成类似以下内容的图表标记:

sequenceDiagram
    autonumber
    participant U  as User (Browser)
    participant FE as Frontend<br/>(api.ts)
    participant PY as Python Backend<br/>(server.py)
    participant BS as BookingService<br/>(booking.py)
    participant QC as QuoteController<br/>(Java)
    participant QS as QuoteService<br/>(Java)
    participant HC as HoldController<br/>(Java)
    participant HS as HoldService<br/>(Java)
    participant DB as Python SQLite
    participant JDB as Java SQLite

    Note over U,JDB: ── Phase 1: Create Quote ──────────────────────────────────

    U->>FE: createQuote({ flightId, seatClass,<br/>quantity, travelerId, travelerName })
    FE->>PY: POST /quotes
    PY->>QC: POST /api/v1/quotes
    QC->>QS: createQuote(request)
    QS->>QS: generateQuoteId() → "Q-2025-000001"
    QS->>QS: pricingService.calculatePrice(flightId, seatClass)
    QS->>JDB: save Quote (status=CREATED, expiresAt=+24h)
    QS->>JDB: save AuditEvent (QUOTE / CREATED)
    QC-->>PY: 201 Quote
    Note right of PY: Returns {"error":"..."} HTTP 200<br/>if Java service unreachable
    PY-->>FE: Quote JSON
    FE->>FE: assertNotProxyError(response.data)
    FE-->>U: quoteId

    Note over U,JDB: ── Phase 2: Create Hold ───────────────────────────────────

    U->>FE: createHold(quoteId)
    FE->>PY: POST /quotes/{quoteId}/holds
    PY->>HC: POST /api/v1/quotes/{quoteId}/holds
    HC->>HS: createHold(quoteId)
    HS->>JDB: findById(quoteId)
    JDB-->>HS: Quote
    HS->>HS: check quote not expired
    HS->>HS: generateHoldId() → "H-2025-000001"
    HS->>JDB: save Hold (status=HELD,<br/>reservedUntil=+15min)
    HS->>JDB: save AuditEvent (HOLD / CREATED)
    HC-->>PY: 201 Hold
    PY-->>FE: Hold JSON
    FE->>FE: assertNotProxyError(response.data)
    FE-->>U: holdId

    Note over U,JDB: ── Phase 3: Confirm Hold → Create Booking ─────────────────

    U->>FE: confirmHold(holdId)
    FE->>PY: POST /holds/{holdId}/confirm
    PY->>HC: POST /api/v1/holds/{holdId}/confirm
    HC->>HS: confirmHold(holdId)
    HS->>JDB: findById(holdId)
    JDB-->>HS: Hold
    HS->>HS: check status == HELD
    HS->>HS: check reservedUntil not passed
    HS->>JDB: findById(hold.quoteId)
    JDB-->>HS: Quote

    HS->>PY: POST /internal/bookings/from-hold<br/>{ travelerId, travelerName, flightId, seatClass }
    PY->>BS: book_flight(db, user_id, name,<br/>flight_id, seat_class)
    BS->>DB: query Flight (check seats available)
    BS->>DB: query User (validate user_id + name match)
    BS->>DB: decrement {seat_class}_seats_available
    BS->>DB: insert Booking (status="booked")
    DB-->>BS: Booking row
    BS-->>PY: BookingOut

    alt booking succeeded
        PY-->>HS: 200 { booking_id, ... }
        HS->>JDB: update Hold (status=CONFIRMED,<br/>externalBookingReference=booking_id)
        HS->>JDB: save AuditEvent (HOLD / CONFIRMED)
        HC-->>PY: 200 Hold (CONFIRMED)
        PY-->>FE: Hold JSON
        FE->>FE: assertNotProxyError(response.data)
        FE-->>U: Booking confirmed ✓
    else booking failed (name mismatch / no seats / user not found)
        PY-->>HS: 400 { error, error_code, details }
        HS->>JDB: update Hold (status=CONFIRMATION_FAILED,<br/>errorMessage=...)
        HS->>JDB: save AuditEvent (HOLD / CONFIRMATION_FAILED)
        HC-->>PY: 400 Bad Request
        PY-->>FE: error response
        FE-->>U: Error shown to user ✗
    end

生成用例图

用例图识别系统中的参与者以及每个参与者可执行的功能。Mermaid 没有原生的用例图类型,因此可以用 flowchart LR 配合 subgraph 来按参与者分组展示用例。

编写一个提示词,识别整个应用程序中的所有参与者及其用例。参与者包括用户类型和外部系统。使用上下文提及来指定 Bob 需要分析的相关文件,包括前端页面、后端 REST 端点和 MCP 工具。你在提示词中越具体地说明要分析哪些文件,输出结果就越准确。此外,还需指示 Bob 对 Mermaid 标记中的花括号进行转义,防止 Mermaid 渲染器将花括号解释为模板语法。

在 Ask 模式下,在聊天输入框中输入以下提示词:

Analyze the full Galaxium Travels application. 

Identify all actors (user types or external systems) and the use cases each
actor can perform, based on the frontend pages, backend REST endpoints,
and MCP tools.

Generate a Mermaid flowchart LR that represents this as a use case diagram,
grouping use cases under their respective actors using subgraphs.

Escape curly braces in Mermaid markup so that the Mermaid renderer does not
attempt to interpret the curly braces as template syntax.

Output the Mermaid markup. Do not render the Mermaid diagram.

Bob 分析应用程序后,会生成类似以下内容的图表标记:

flowchart LR

    subgraph Traveller["👤 Traveller (Browser)"]
        T1[Browse available flights]
        T2[Search flights by origin / destination]
        T3[Filter flights by date, price, seat class,\nduration, route category, time period]
        T4[Register account]
        T5[Sign in with name and email]
        T6[Select seat class\neconomy / business / galaxium]
        T7[Get price quote]
        T8[Place seat hold - 15-minute timer]
        T9[Confirm hold and create booking]
        T10[Release hold]
        T11[View active bookings]
        T12[View past bookings]
        T13[Cancel booking]
        T14[View pending holds with countdown]
        T15[Dismiss expired hold]
    end

    subgraph AIAgent["🤖 AI Agent (MCP Client)"]
        A1[list_flights]
        A2[register_user]
        A3[get_user_id]
        A4[book_flight]
        A5[get_bookings]
        A6[cancel_booking]
    end

    subgraph JavaService["☕ Java Hold Service\n(Internal System)"]
        J1[Confirm hold via POST /internal/bookings/from-hold]
        J2[Auto-expire holds after timeout]
    end

    subgraph RestAPI["🐍 Python REST API\n(External Consumers / Swagger)"]
        R1[GET  /flights — list and filter flights]
        R2[POST /register — register user]
        R3[GET  /user — look up user by name and email]
        R4[POST /book — book a flight]
        R5[GET  /bookings/&#123;user_id&#125; — get user bookings]
        R6[POST /cancel/&#123;booking_id&#125; — cancel booking]
        R7[POST /quotes — create quote proxy]
        R8[GET  /quotes/&#123;id&#125; — get quote proxy]
        R9[POST /quotes/&#123;id&#125;/holds — create hold proxy]
        R10[GET  /holds/&#123;id&#125; — get hold proxy]
        R11[POST /holds/&#123;id&#125;/confirm — confirm hold proxy]
        R12[POST /holds/&#123;id&#125;/release — release hold proxy]
        R13[GET  / — health check]
    end

    Traveller   -->|uses frontend which calls| RestAPI
    AIAgent     -->|MCP over HTTP at /mcp| RestAPI
    JavaService -->|calls back via internal endpoint| RestAPI

将图表保存到代码仓库

将 Bob 切换到 Agent 模式,并让它将你生成的图表保存到代码仓库中。每个图表将作为一个 Markdown 文件保存在新建的 docs/architecture/ 文件夹中。

切换到 Agent 模式

在模式选择器中选择 Agent,或在聊天输入框中输入 /agent

保存全部三个图表

让 Bob 创建架构文档文件。

Create a docs/architecture/ folder in the repository root.

Save each of the three diagrams we generated as individual Markdown files:
- class-diagram.md — the UML class diagram
- sequence-diagram.md — the booking flow sequence diagram
- use-case-diagram.md — the use case flowchart

Each file should have a short title heading, the Mermaid code block we
generated, and a brief description of the diagram.

Bob 会创建这三个文件。对于 Bob 写入的每个文件,点击批准保存

验证输出结果

在 Bob 文件浏览器中打开每个文件,确认 Mermaid 代码块已正确写入。你可以通过以下几种方式验证图表:

  • 让 Bob 为你预览 Markdown 文件。

    在聊天输入框中输入以下提示词:

      Show me a preview of docs/architecture/class-diagram.md

    Bob 会在聊天界面中渲染 Markdown 文件,包括其中的 Mermaid 图表。点击渲染后的图表可在更大的视图中查看。

    你可以对三个文件依次执行此操作,查看所有图表的渲染效果。

  • 将图表标记粘贴到 Mermaid Live Editor 中预览渲染结果。

  • 将修改 commit 并 push 到 GitHub 仓库,然后在 GitHub 上查看文件,即可看到渲染后的图表。

故障排查

Bob 生成的 Mermaid 标记无法编译

Mermaid 的解析器非常严格。哪怕是一个无效字符、不支持的关键字,或者缺少换行符,都可能导致图表静默失败或抛出解析错误。使用以下方法来诊断和修复问题。

定位出错的行

当 Bob 产生解析错误时,输出中会包含行号以及出错代码片段。

如果 Bob 没有输出解析错误,可以将标记粘贴到 Mermaid Live Editor 中。编辑器会高亮出错行并显示解析错误,帮助你定位问题所在。

你也可以直观地检查标记,查找常见问题,例如标签中未转义的特殊字符、未关闭的 subgraph,或箭头语法错误。

现象可能原因修复方法
{} 附近出现解析错误flowchartclassDiagram 节点标签中的花括号未转义{ 替换为 &#123;,将 } 替换为 &#125;,或改写标签文字
() 附近出现解析错误节点 ID 中包含括号将标签用引号括起来:A["label (note)"]
出现意外的 endsubgraph 错误subgraph 未关闭确保每个 subgraph 块都有对应的 end
不识别箭头类型图表类型使用了错误的箭头语法--> 用于 flowchartclassDiagram 使用 -->..>--|> 等;sequenceDiagram 使用 ->>-->>
节点已定义但未连接孤立节点不会报错,但可能导致某些渲染器出现混乱将该节点连接到其他节点,或将其删除
图表渲染到一半后中断标签中包含裸 " 字符对标签内的引号进行转义:A["it\'s a label"]

让 Bob 修复问题

将解析错误和出错行提供给 Bob,然后让 Bob 修复特定的行。

示例:

The Mermaid classDiagram fails to parse with this error:
Parse error on line 42: ...unexpected token 'NEWLINE'

Here is the relevant block:
    Booking ..> BookingStatus : status (active)

Fix the syntax so it compiles without changing the diagram structure.

Bob 可以精准修复特定问题,而无需重新生成你已经审查过的内容。

让 Bob 在输出前进行验证

如果你要从头重新生成图表,可以在提示词中加入显式的验证指令:

Before outputting the Mermaid block, mentally parse it and confirm every node ID
is valid, every subgraph is closed, and all special characters in labels are escaped.

缩小图表的范围

如果包含大量节点的图表反复生成无效标记,可以让 Bob 分段生成,例如先生成 Python 模型,再生成 Java 模型,最后让 Bob 将各段拼合在一起。分段生成更便于 Bob 进行验证,也更便于你进行对比检查。

后续步骤

在本教程中,你使用上下文提及和 Ask 模式探索了 Galaxium Travels 代码库,并借助 Bob 生成了三种类型的架构图,然后使用 Agent 模式将它们保存到了代码仓库。继续探索以下资源:

  • 浏览 Bob 入门教程,深入了解 Bob 在 Galaxium Travels 应用中的更多能力。
  • 参考规划并实现复杂功能教程,学习如何使用 Plan → Agent 模式工作流为应用添加新功能。
  • 阅读 Bob 最佳实践,学习使用 Bob 的高效提示策略。
这个主题怎么样?