生成AIによるコードベース解析（その１）

## はじめに

この記事は、**生成AIによるコードベース解析** というテーマでの実験内容をまとめています。

生成AIの進化によりClineやbolt.newといったツールで、アイデアベースをあっという間にPoCレベルのシステムに仕上げることが出来るようになってきました。

一方で、業務システムの現場では依然として以下のようなことが課題となっています。[一部推測]

- 複雑で大きな**コードベースを分析し理解**するのが困難
- 新規開発よりも**保守（メンテナンス）が多く**、ちょっとした修正でも影響調査やテストは工数が膨大
- 生成AIの効果がなかなか実感しづらい

というわけで、ある程度の大きさのコードベースを現在の生成AIツールがどの程度解析できるか？というのを試してみたいと思います。

## 実験のおおまかな流れ

- ある程度の大きさのコードベースを用意する
  - とはいえ、みんなで共有できる「ある程度のコードベース」を用意するのは大変
  - 書籍で公開されているサンプルアプリケーションを題材にして、まずは、実装を進る

- 上記に対して、機能の追加や改修を行う

- 使う生成AIツールも、社内で利用可能なものを中心として、一部、先端的なものを比較対象として取り入れる

※ ある程度の大きさのコードベースを目指していましたが、準備時間の都合上、まだ5,000行程度です。

### 題材のアプリケーション

**Eric Evans著「Domain-Driven Design」** の第8章ブレークスルーで紹介されている「**シンジケートローン**」を取り扱います

### 生成AI利用シーン

一旦、バックエンド（RestAPI）の仮実装が済んだ状態で、
- あるユースケースの実装を仕上げる部分
- 機能の追加をする
といったシーンを想定しています。

第一回（その１）では、準備の都合上、「あるユースケースの実装を仕上げる部分」として、「**シンジケートローンのDrawdownというユースケース**」を取り上げます。

### 使う生成AIツール

ここでは顔ぶれだけ簡単に紹介します。詳しい内容は後述します。

- GitHub Copilot Chat
- Roo-Cline (Copilo LM API)
- Cursor
- GitHub Copilot - Edit with Copilot

## 詳細

### 題材アプリケーションの紹介

前述の通り、シンジケートローンを取り扱う訳ですが、内容は書籍を読むのが一番です。
原著のPDF版がネットにあるのでリンクを置いておきます。(P.136~)
https://fabiofumarola.github.io/nosql/readingMaterial/Evans03.pdf

最終的なイメージはこちらのクラス図になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130262/1daa1f8e-ea1f-ad37-13b2-e7f4ddb8336a.png)

**原著を読むのが大変なので、生成AI（Bedrock Claude Chat）に、PDFを登録し、簡易RAGにより、要点をまとめ**てもらいました。
ここは少々長いので、折り畳みセクションにします。この内容はコンテキストとして、コード解析やコードサジェスチョンの際の生成AIへの入力としても使います。
（本実験の主旨から脱線しますが、生成AIによる要点まとめがかなり秀逸でした。）

:::note info
下記の要約もかなり長いので、要約の要約を生成AIに作ってもらいました。
1. 複数の貸し手が共同で大規模なローンを提供する仕組み

2. 主要エンティティとして、Position（ポジション）、Transaction（取引）、Facility（融資枠）、Loan（ローン）がある

3. 資金の流れを追跡し、投資家間での分配を管理するための SharePie と AmountPie を実装

4. ドローダウン、利息支払い、元本返済など、様々な取引タイプをサポート

5. 借り手、投資家、シンジケート団などの関連エンティティも考慮し、複雑な金融取引を総合的に管理
:::


<details>
<summary>
書籍の要約
</summary>

# シンジケートローンアプリの概要

## シンジケートローンの概要

以下にシンジケートローンに関する情報をまとめます：

1. シンジケートローンは、単一の貸し手が引き受けるには大きすぎるローンを複数の貸し手が共同で提供する仕組みです。
2. 例えば、Intelが10億ドル規模の工場を建設する際に必要な巨額の融資は、通常、複数の貸し手が「シンジケート」を形成して資金を提供します。
3. 投資銀行が通常シンジケートのリーダーとして機能し、取引や他のサービスを調整します。
4. ローンの借り手が資金を要求すると、シンジケートのリーダーは全メンバーに対して各自の持分を呼び出します。
5. シンジケートメンバーは通常、自身の持分を提供しますが、しばしば他のメンバーと交渉して投資額を増減させることがあります。
6. モデルにはLoan Investment（ローン投資）という派生オブジェクトがあり、これは特定の投資家のローンへの貢献を表します。
7. ファシリティ（融資枠）の持分は、実際のローン引き出し（ドローダウン）への参加のガイドラインにすぎません。
8. 借り手がファシリティを利用できる特権に対して手数料を支払う場合、この資金はローンの状況に関係なく、ファシリティの持分に応じて分配されます。

このシステムは、複雑な金融取引を管理し、異なる参加者間での資金の分配や調整を行うためのものです。

## データモデル（エンティティレベル）

ご提供いただいた図を確認しました。この図は、シンジケートローンのデータモデルを表すクラス図であると理解できます。以下に、図から読み取れるエンティティとその関係性を説明します：

1. Position（ポジション）
   - Share Pie（シェアパイ）との関連
   - Facility（ファシリティ）とLoan（ローン）の親クラスとして機能

2. Transaction（取引）
   - Position（ポジション）と関連
   - Amount Pie（金額パイ）との関連
   - 「Transactions focus on money flow, but they never change positions if at all」というコメントあり

3. Facility Investment（ファシリティ投資）
   - Transaction（取引）のサブクラス

4. Facility Trade（ファシリティ取引）
   - Transaction（取引）のサブクラス

5. Drawdown（ドローダウン）
   - Transaction（取引）のサブクラス

6. Fee Payment（手数料支払い）
   - Transaction（取引）のサブクラス

7. Interest Payment（利息支払い）
   - Transaction（取引）のサブクラス

8. Principle Payment（元本支払い）
   - Transaction（取引）のサブクラス

9. Facility（ファシリティ）
   - Position（ポジション）のサブクラス

10. Loan（ローン）
    - Position（ポジション）のサブクラス

11. Share Pie（シェアパイ）
    - Position（ポジション）と関連

12. Amount Pie（金額パイ）
    - Transaction（取引）と関連

ポジションと取引の関係性を中心に構成されており、各種取引（ドローダウン、手数料支払い、利息支払いなど）がTransactionのサブクラスとして表現されています。また、FacilityとLoanがPositionのサブクラスとして示されており、シンジケートローンの構造を反映しています。

## データモデル（主要項目を追記）

はい、提供された情報と推測して、各エンティティが保持すべき項目を設計してみます。

1. Position (ポジション)
   - id: 一意識別子
   - type: ポジションタイプ（Facility or Loan）
   - amount: 総額
   - sharePie: 関連するSharePieへの参照

2. Facility (ファシリティ)
   - id: 一意識別子
   - totalAmount: 融資枠総額
   - availableAmount: 利用可能額
   - term: 期間
   - interestRate: 金利

3. Loan (ローン)
   - id: 一意識別子
   - totalAmount: ローン総額
   - borrower: 借り手情報
   - term: 期間
   - interestRate: 金利

4. Transaction (取引)
   - id: 一意識別子
   - date: 取引日
   - amount: 取引金額
   - relatedPosition: 関連するPositionへの参照
   - amountPie: 関連するAmountPieへの参照

5. Facility Investment (ファシリティ投資)
   - investor: 投資家情報
   - investmentAmount: 投資額

6. Drawdown (ドローダウン)
   - drawdownAmount: 引き出し額
   - relatedFacility: 関連するFacilityへの参照

7. Fee Payment (手数料支払い)
   - feeType: 手数料タイプ
   - paymentAmount: 支払い金額

8. Interest Payment (利息支払い)
   - interestRate: 適用金利
   - paymentAmount: 支払い金額

9. Principal Payment (元本支払い)
   - paymentAmount: 支払い金額

10. Share Pie (シェアパイ)
    - shares: シェア情報のリスト（投資家とその割合）

11. Amount Pie (金額パイ)
    - amounts: 金額配分情報のリスト（投資家と金額）

12. Facility Trade (ファシリティ取引)
    - seller: 売り手情報
    - buyer: 買い手情報
    - tradeAmount: 取引金額

これらの設計は、シンジケートローンの複雑な構造を反映しています。例えば：

- PositionはFacilityとLoanの親クラスとして機能し、共通の属性を持ちます。
- TransactionはPositionに関連付けられ、金銭の流れを追跡します。
- FacilityとLoanは異なる特性を持ち、それぞれ融資枠と実際のローンを表現します。
- Share PieとAmount Pieは、投資家間の分配を管理するために使用されます。

この設計により、シンジケートローンの複雑な取引や資金の流れを効果的に管理できると考えられます。

## モデル図に省略されているが必要となりうるエンティティ

図に直接表れていないものの、シンジケートローンシステムにとって重要なエンティティがいくつかあります。これらを含めて、追加のエンティティを抽出し、設計してみます：

1. Borrower (借り手)
   - id: 一意識別子
   - name: 企業名または個人名
   - creditRating: 信用格付け
   - financialStatements: 財務諸表情報
   - contactInformation: 連絡先情報

2. Investor (投資家)
   - id: 一意識別子
   - name: 機関名または個人名
   - type: 投資家タイプ（銀行、投資ファンドなど）
   - investmentCapacity: 投資能力
   - currentInvestments: 現在の投資額合計

3. Syndicate (シンジケート団)
   - id: 一意識別子
   - leadBank: 幹事銀行（リーダー）
   - members: メンバーリスト（Investorへの参照）
   - totalCommitment: 総コミットメント額

4. Company (企業)
   - id: 一意識別子
   - name: 企業名
   - industry: 業種
   - financialInformation: 財務情報

5. Currency (通貨)
   - code: 通貨コード
   - name: 通貨名
   - exchangeRate: 為替レート

6. InterestRateType
   - id: 一意識別子
   - name: 金利タイプ名（固定金利、変動金利など）
   - description: 説明

7. FeeType
   - id: 一意識別子
   - name: 手数料タイプ名
   - description: 説明

8. TransactionType
   - id: 一意識別子
   - name: 取引タイプ名
   - description: 説明

これらの追加エンティティを考慮することで、システムはより完全になります：

- BorrowerとInvestorは、ローンとファシリティの主要な参加者を表現します
- Syndicateは、複数の投資家がどのように組織化されているかを示します
- Companyは、BorrowerやInvestorが企業である場合に使用できます
- Currencyは、国際的な取引を扱う際に重要です
- InterestRateType、FeeType、TransactionTypeは、様々な金利、手数料、取引の種類を分類するのに役立ちます

これらのエンティティを既存のモデルに統合することで、シンジケートローンの複雑な関係性やプロセスをより詳細に表現できるようになります。例えば、LoanはBorrowerへの参照を持ち、FacilityはSyndicateへの参照を持つことができます。また、TransactionはTransactionTypeを持つことで、より詳細な分類が可能になります。

## 補足（Transactionのサブタイプごとの資金の流れ）

Transactionのサブタイプごとの資金の流れを説明します。

1. シンジケートの組成について：
はい、その理解で正確です。ファシリティを複数の出資者が組成することは、シンジケートの組成と言い換えても適切です[^0]。シンジケートローンでは、複数の金融機関（投資家）が協調してローンを提供するため、このプロセスをシンジケートの組成と呼びます。

2. Transactionのサブタイプごとの資金の流れ：

a) Facility Investment（ファシリティ投資）:
   投資家 → シンジケート（ファシリティ）
   各投資家がシンジケートに資金を提供します。

b) Drawdown（ドローダウン）:
   シンジケート（ファシリティ） → 借り手
   借り手がファシリティから資金を引き出します。

c) Interest Payment（利息支払い）:
   借り手 → シンジケート → 投資家
   借り手が支払った利息がシンジケートを通じて投資家に分配されます。

d) Principal Payment（元本返済）:
   借り手 → シンジケート → 投資家
   借り手が返済した元本がシンジケートを通じて投資家に分配されます。

e) Fee Payment（手数料支払い）:
   借り手 → シンジケート → 投資家
   借り手が支払った手数料（ファシリティ利用料など）がシンジケートを通じて投資家に分配されます。

f) Facility Trade（ファシリティ取引）:
   投資家A → 投資家B
   投資家間でファシリティのシェアが取引されます。実際の資金移動は投資家間で直接行われる場合もありますが、シンジケートを通じて行われることもあります。

これらの取引において、シンジケート（通常はリード銀行が管理）が資金の集中と分配の役割を果たします。各取引は、関連する Share Pie や Amount Pie に基づいて処理され、投資家間での適切な資金配分が行われます。

</details>


### 生成AI利用シーン

前述の通り、今回（その１）は、準備の都合上「あるユースケースの実装を仕上げる部分」として、「**シンジケートローンのDrawdownというユースケース**」を取り上げます。

※ なお、この部分は概略だけ理解いただければOKです。

詳しくは勉強会で話しますが、これ以前に
- マスターとなる借り手、貸し手（シンジケートローンへの出資者）の登録
- シンジケートの組成（Facilityと呼ぶ）

が済んでいる状態です。

その前提で、DrawdownのRequestイメージと結果として作られるエンティティの状態を示します。

■Request (curl のリクエスト）

```bash
curl -X POST http://localhost:8080/api/drawdowns \
  -H "Content-Type: application/json" \
  -d '{
    "relatedFacilityId": 1,
    "drawdownAmount": 2000000,
    "date": "2025-01-31T14:00:00",
    "processedDate": "2025-01-31T14:00:00",
    "relatedPositionId": 1,
    "amountPie": {
      "amounts": {
        "1": 400000,
        "2": 1600000
      }
    }
  }'
```

■エンティティの状態（事後状態）
融資額が巨額なので、投資家シンジケート（ここでは２社）が出資して融資実行したという状態
![ddd-breakthrough-entity.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130262/6a04b4af-4e2c-93c9-1c8d-840d396def1b.png)


## 使う生成AIツールの紹介と今回の成果！

どのツールのおいても、実装追加前のDrawdownの処理を解析してもらい、そのうえで、修正の依頼をしています。

### 🤖GitHub Copilot Chat
■概略
- GitHub Copilotの関連ツールでChat形式で生成AIと対話が可能
- 当社のスキームでGitHub Copilotを契約していれば特に追加費用なしに利用可能
- Indexから参照すべきコードを判定（中身はブラックボックス）

■今回の結果

悪くはないが、コードの解析において基底クラスを考慮していない動きをしているように見える

■やり取りのログは長いのでGitHub参照

https://github.com/tis-abe-akira/ddd-breakthrough/blob/ba03066935cfc862c255e3d1a7232e73fc450c4a/backend/copilot_chat.md


### 🧙‍♂️Roo-Cline (Copilo LM API)

■概略
- OSSのCode生成エージェント（ClineのFork版）
- VSCodeの拡張機能としてインストールできる
- これ自体は無料だが、別途LLMのAPIを利用設定する必要がある
    - OpenAI, Anthropic, Gemini, Azure, AWSBedrockなどに対応（別途API利用料がかかる）
    - GitHub CopilotのLMAPIにも対応しておりGitHub Copilotのライセンスがあれば、別途費用は掛からない
        - ただし！使いすぎてAbuseと見なされ、アカウント停止された例がXで報告されている！
        - https://zenn.dev/ymsy/articles/4cbf29f2f3272a
- tree-sitterによる構文解析（AST） + ripgrep による検索で解析頑張っている（kirikirimodeさん調べ）

■今回の結果

**精度は良い**
コード解析や修正についても優れている
ただし、**利用に際してはAPIを別途登録するので、注意事項が多い**！

■やり取りのログは**非常に長い**のでGitHub参照

https://github.com/tis-abe-akira/ddd-breakthrough/blob/9b178a213cf7681e6c570e5fbf0c7ec9b25d81b0/backend/cline-log/cline_task_jan-22-2025_3-37-56-pm.md



### 🦉Cursor (Composer normal mode)

■概略
- GitHub Copilotとは競合する位置づけのAI統合型のエディター
- 無償でも使えるが実践的な利用は有償ライセンスが別途必要
- Ragから参照すべきコードを判定（中身はブラックボックス）

■今回の結果

**精度は良い**
コード解析や修正についても優れている
今回の評価観点ではないがUI/UXが非常に洗練されている

■やり取りのログは長いのでGitHub参照

https://github.com/tis-abe-akira/ddd-breakthrough/blob/f0e783a55e5b48301f185440ea114895b7d93fa1/backend/cursor_composer.md


### 📚GitHub Copilot - Edit with Copilot

■概略
- GitHub Copilotの関連ツールでChatの上位機能で複数のコードを並列で編集する（preview版）
- 当社のスキームでGitHub Copilotを契約していれば特に追加費用なしに利用可能
- Indexから参照すべきコードを判定（中身はブラックボックス）

■今回の結果

一部の**プロンプトを補正した結果飛躍的に精度向上**（他とイコールコンディションではない）
エージェントではないので、コンパイルエラー訂正などを自動でやってくれないが、メンテナンスのフェーズでは**十分実用的**と思われる

■やり取りのログは長いのでGitHub参照

https://github.com/tis-abe-akira/ddd-breakthrough/blob/301f6d56334c4b27b9205bf1845bc99c00a883ad/backend/edit_with_copilot.md


## 結果のまとめ

今回は、利用したツールにより若干の優劣はあるものの、最終的にはプロンプトの工夫により同じレベルの精度が保たれるため、**圧倒的な優劣はない**と考えられます。

また、以下の点は評価の際に考慮しておく必要があると思います。
- 一番最後に使用した**Edit with Copilotはプロンプトを改善しているため、状況がかなり有利**であった
- これはコードベースがさほど大きくない
- 修正内容が特定のユースケースに閉じている（さほど範囲が広くない）
- 各々のツールで１回程度の実行なので、優劣が、ツールの差なのか？LLMの回答のバラツキなのか？までは評価できない

ツール毎の評価まとめ：


|評価項目  |Copilot Chat  |Roo-Cline(*6)  |Cursor |Edit with Copilot |
|---|---|---|---|---|
|コードベース解析精度(*1)  |△(*2) |○  |○  |○  |
|コード修正の質 |△ |○ |○ |◎(*3) |
|費用(*4) |なし |API利用料別途(*5) |ライセンス料必要 | 不要 |
|その他の利点  |  |LLMとのやり取りをExport出来る。<br/>内部動作がOSSで公開されている。  |UI/UXが洗練されておりエージェント機能もある  |  |

 *1 純粋に解析精度を図るのは難しく、LLMによる説明文の質が評価に影響を与えている面はある

 *2 Edit with Copilotは”○”なので、回答のバラツキの可能性もある

 *3 基底クラスに個別ロジックを追加しないようにプロンプトで誘導したため、他と比べて状況が有利

 *4 当社のスキームでのGitHub Copilotライセンスはある前提

 *5 Roo-ClineからCopilot LM APIを呼ぶ場合には不要だが、多用するとアカウント停止されるという報告アリ。通常の利用では別途API利用料が必要。

 *6 Cline系（Cline、Roo-Clineなど）は、大きなコードベースや会話が長くなった場合に精度が出ないという評価がSNS（Xなど）で上がっている。それを示唆する情報としては、以下のものがあげられる。

 - ClineがContextに入りきらない内容を切り捨てているコード部分（kirikirimodeさんより）
 https://github.com/cline/cline/blob/v3.2.0/src/core/Cline.ts#L1234-L1270

 - Clineに対してRAG実装の要望が上がっている
 https://github.com/cline/cline/discussions/1255

## 示唆・要確認事項

### コード解析は単純なRAGだと精度が出ないのでは？

今回評価対象に入れていませんが、RAG（ベクトル検索）にソースを入れて、解析を試し見たところ、期待した精度が出ませんでした。一方で、構文解析（メソッドシグネチャーの抽出程度らしいが）をしているClineはなかなかの精度でした。
ここから得られる示唆としては、コード解析は単純なRAGではいまいちうまくいかないのでは？ということ。

### もっと大規模になった時にどうなるか？

例えばClineは「コードベースをタスクの都度構文解析している」ため、超大規模になった時に、処理速度や精度がどうか？というのは気になる。
（前述の通り、コンテキスト切り捨てなどもあり大規模の場合には厳しいと思われる。）

また、CopilotやCursorが使っているとされるIndexも超大規模の場合には上手く機能するのか？というのも気になる。

### 自然言語からの設計成果物作成

今回の検証範囲からは外れるが、簡易RAGでかなり良い感じの仕様定義が書けそうなので、この分野も検証の価値がありそう。

## これからの取り組み

### ぜひ皆さんのプロジェクトでも試してみてほしい！

Copilot Chatでのコード解析については、すぐに試せるので、ぜひ情報を共有してほしいです！
`#codebase` を付けるのがポイントです。

### 次回以降（来週できるかなぁ？）

この題材で、ユースケースを追加し、フロントエンドも追加して、また、情報共有したいと思います！
このツールも試してほしいなどありましたら、ご連絡ください！！

## 参考情報

今回のコード規模： 
- Javaファイル数 77クラス
- コード行数　約5,000行