🍣

開発チーム・AIチーム間のシステム境界と責任境界について

に公開

はじめに

こんにちは。AI Shift バックエンドエンジニアの木村です。
私たちのプロダクトでは開発チーム(フロント、バック、インフラ)とAIチーム(自然言語処理、音声対話など)が共同して開発しています。
開発プロセスの中で開発チームのバックエンドエンジニアとAIチームが連携することが多く、その中で感じた課題や改善案、実際に現在行なっていることをまとめてみました。

背景と目的

私たちのプロダクトは音声対話に関わるプロダクトで、AIチームの専門性とバックエンドエンジニアの専門性をどう効率よく連携させるかという課題がありました。
それまで2パターンの連携方法を試していました。

  1. Pythonでプロトタイプ → Goでプロダクトに組み込み
    AIチームがPython(Jupiter NotebookやGradio)でプロトタイプとして実現方法を検証し、バックエンドエンジニアがプロダクトにGoで組み込むというアプローチをしていました。プロトタイプ検証が終わっても開発チームのスケジュールにのせると最終的なリリースまでにはそれなりの時間がかかってしまう課題がありました。

  2. GoサーバとPythonサーバでAPI連携
    AIチームがPythonで独自のサーバーを開発・運用し、開発チームのGoサーバーとREST/HTTPによるAPI連携を行うアプローチです。AIチームは得意な言語環境で開発できるメリットがあり、プロトタイプで検証したロジックをそのまま流用することができました。
    ただ、本番運用となるとパフォーマンスや障害検知、データの整合性などバックエンドの専門性をAIチームに求めることになりAIチームの負担が大きくなってしまいました。
    また、マイクロサービス的な視点ではAIチームの管理するサービスで使用するデータは外に漏らさずサービス内で管理することが望ましいですが、マスタデータの管理は開発チームの管理画面で管理するようになっていました。

課題の整理と検討ポイント

これまでの2つのアプローチから浮かび上がった課題は以下の通りです。

  • 開発効率の低下: 「Pythonでプロトタイプ→Goで実装」アプローチでは、AIチームが作成したプロトタイプを開発チームが再実装する必要があり、同じ機能を二度作ることになります。また、プロダクトに組み込むときになって初めて他の仕様との整合性など新たな問題が発覚しリリースまでの時間が長期化していました。

  • 言語とフレームワークの分断: AIチーム(Python)と開発チーム(Go)の異なる言語環境は、コード共有や相互レビューを困難にし、チーム間の知識共有の障壁となっていました。

  • 運用負担の増大: 「GoサーバとPythonサーバのAPI連携」アプローチでは、AIチームが本来の専門分野ではないサーバー運用やパフォーマンスチューニング、障害対応などに時間を取られ、本来の研究開発に集中できなくなっていました。

  • 責任境界の曖昧さ: データの整合性管理や障害発生時の対応など、どちらのチームが責任を持つべきか不明確なケースが発生していました。マスタデータは開発チームの管理画面で管理されながらも、AIチームのサービスでも利用するという矛盾が生じていました。

  • システム全体の複雑化: 複数のサービスによる連携は、データの一貫性確保やエラーハンドリングを複雑にし、デバッグや障害対応の難易度を上げていました。

これらの課題を解決するためには、各チームの専門性と強みを活かしつつ、効率的な連携を可能にする新たなアプローチが必要です。理想的には、AIチームが研究開発に注力でき、かつその成果をスムーズにプロダクトに組み込める仕組みが望ましいと考えました。

理想の状態

上記の課題から以下を理想状態と考えました。

  • サーバー管理などのインフラ運用は、品質と安定性を担保するために開発チームが一元管理
  • AIチームが概念検証や実現可能性の検証のための実装を素早くできる状態は維持する
  • 上記の実装を素早くプロダクトに実装できる
  • パフォーマンス、スケーラビリティ、並行処理におけるデータの一貫性、障害検知などはバックエンドエンジニアが担保しやすい構成
  • 双方の責任範囲が明確

検討したアプローチと結果

以下の技術的アプローチを検討し、それぞれのメリット・デメリットを比較しました。

アプローチ 概要 メリット デメリット
1 Pythonでプロトタイプ、Goでプロダクト実装 AIチームは研究開発に専念、実装は開発チームが一括担当 それぞれの専門性を活かしやすい 2回作る非効率さ、引き継ぎのコスト
2 GoサーバとPythonサーバでAPI連携 AI機能を独立サービス化し、APIで連携 システム境界の明確化、各チームの技術的自由度の確保 AI側もインフラ管理が必要、監視や性能面でAIチームの負担増
3 Goサーバ上でcgo呼び出し AIチームの成果物をGoからcgoを介して呼び出す モデル資産を活かしつつ開発チームでのサーバ管理 メモリリークのリスク、エラーハンドリングの困難さ、トラブルシューティングの困難さ
4 Goサーバ上でPythonをコマンド実行 別プロセスとしてPythonスクリプトを実行 シンプルな実装、開発チームでのサーバ管理 起動オーバーヘッドが大きく、頻繁な呼び出しには不向き
5 AIチームもGoで実装 AIチームのプロトタイプはプロダクト上でGoで実装 連携の技術リスク低減、スムーズなコードレビューが可能 Pythonの利点が活かせず、AIチーム内の学習コスト、責任範囲の曖昧さ

各アプローチの採用/不採用理由は以下の通りです:

1. Pythonでプロトタイプ、Goで本番実装

不採用理由: 前述の通り。

2. GoサーバとPythonサーバでAPI連携

不採用理由: 前述の通り。

3. Goサーバ上でcgo呼び出し

不採用理由: cgo呼び出しによるパフォーマンスオーバーヘッドやメモリ管理の複雑さ、デバッグの難しさを考慮し、安定性に懸念がありました。
また、cgoはシンプルな技術に比べて低レベルなインターフェース間の連携が必要となり、未知のトラブルが発生した際の対応が困難になるリスクがありました。

4. Goサーバ上でPythonをコマンド実行

不採用理由: AIチーム側のコードをpythonコマンドで呼び出せるようにし引数はJSON文字列というルールにする方法で検討しました。枯れた技術に依存することで不要なトラブルシューティングの難易度上昇を防止できると考えました。しかし、リクエストごとのプロセス起動オーバーヘッドが大きいことやエラーハンドリングが複雑になるという課題もあり、またPython側からGoへのコールバック処理は構造上しにくいという懸念もあがりました。

5. AIチームもGoで実装 (採用)

検討内容と採用理由:
当初はAIチームにとってのGo言語の学習コストを懸念していましたが、Goの言語仕様のシンプルさと、AIチームのエンジニアの習得意欲の高さから、この課題は克服可能と判断しました。また、開発チームがAIチームをサポートする体制を整えることで、スムーズな移行が可能になると考えました。
また、プロダクトコードはClean Architectureでドメインロジックをその他と切り分けておりコード上での責任境界も決めやすいと考えました。

私たちの実践事例

私たちは検討の結果、5の『AIチームもGoで実装』を採用しました。検討過程で決めたことや実践する中で新たに決めたことを整理します。

  1. 共通言語としてのGo

    AIチームの学習コストが懸念でしたが、シンプルな言語仕様のおかげもあって各自独習してもらったうえでペアプロなどを通じて徐々にClean ArchitectureやDDDなどバックエンド特有のアーキテクチャにも慣れていってもらっています。また、Cursorによるコーディング支援も新しい言語へのスムーズな移行に大きく貢献しています。

  2. AIチームのプロトタイプも正式プロダクトのアーキテクチャ上で開発する

    主要となるドメインロジックをストラテジーパターンで整理し、新機能を既存機能に影響なく追加しやすくしました。これによりAIチームが作るプロトタイプもプロダクト上で開発できるようになり開発プロセス全体としての開発効率が上がりました。
    具体的にはドメインロジックをシーンという単位でまとめており、以下のような構成にしました。

シーンとして作成した対話ロジックを音声対話以外のテキストチャット等に転用することも(Callerを別に作り音声関連のメソッドを呼ばないようにすれば)可能になりました。

  1. コード上での責任範囲

    • ドメインモデルは開発チーム、AIチームどちらも責任を持つ
      • モデルの構造やロジックは必要にどちらも修正する
    • Clean Architectureの維持は開発チームの責務
    • DBアクセスは開発チームが責任を持つ
      • プロトタイプ時はデータはコード上にベタ書き
      • プロダクト実装のときのドメインモデルからテーブル定義にするところは開発チームが責任持ちつつ一緒に議論する
      • トランザクション管理、データアクセスのパフォーマンスなどは開発チームの責務
    • 音声処理など一部のinfrastructure(Clean Architectureでの)はAIチームが責任を持つ
    • LLM関連の処理はAIチームの専門部分もあるが開発チームも修正する
    • 管理画面からのデータ編集は開発チーム
  2. 開発チームによるインフラ管理

    サーバー運用、CI/CD、セキュリティなど、システム全体の品質と安定性を確保するため、インフラ管理は開発チームが一元的に担当しています。

  3. タスク管理の統合

    プロダクト開発に関するタスクの管理は同じスクラム開発上のスプリントで管理しスクラム関係のミーティングも統合しています。ただしAIチームの研究関連のタスクやミーティングは別にしていて、結果AIチームのミーティングが増えたことは影響としてあります。

  4. AIチームのリサーチ期間は独立して動く

    AIチームは独立して動くリサーチ期間と開発チームと一緒に動く期間を分けました。また、それはチーム単位ではなくメンバー単位で考えます。上記のタスク管理の統合は一緒に動く期間に限定します。

半年実践してみて感じた効果

開発速度は体感ですがプロトタイプ2週間、プロダクト実装4週間かかっていたものがプロトタイプ実装2週間、プロダクト実装2週間くらいになりました。
プロトタイプの段階からAIチームとバックエンドで一緒に実現方法を考えられること、またプロトタイプからプロダクト実装に引き継ぐときもドメインモデルを一緒にリファクタリングしながら行うことで全体の効率が上がってると思います。
デメリットとしてはAIチームのミーティング時間が増えたことがあります。設計議論やスクラム関係のミーティングです。ある程度必要なことだと思っていますが今後最適化していきたいと思います。

思わぬ効果

同じ言語を使い同じコードベースで作業するようになり、同じ会議に参加することが多くなったためか、開発チームとAIチームの距離が縮まりました。以前より同じプロダクトを一緒に作ってるという感覚が強くなり、プロダクトのあるべき仕様や作りのあるべきをいろんな視点で議論できるようになりました。
結果、みんなのプロダクト愛が高まりました。

まとめ

開発チーム(主にバックエンド)とAIチームの連携において、当初は開発効率の低下、言語の分断、運用負担の増大といった課題がありました。これらの課題を解決するため、複数のアプローチを検討した結果、「AIチームもGo言語で実装する」という方針を採用しました。

具体的には、Go言語を共通言語とし、主要なビジネスロジックをプラグインアーキテクチャ化することで、AIチームもプロダクトコード上でプロトタイプ開発を行えるようにしました。また、コード上の責任範囲を明確化し、インフラ管理は開発チームが一元的に担い、タスク管理も統合しました。

この取り組みにより、開発速度の向上、チーム間の連携強化、そしてプロダクト愛が高まるといった効果を実感しています。本記事で紹介した課題や実践内容が、同様の課題を抱えるチームにとって少しでも参考になれば幸いです。

プロダクトの紹介

今回の事例の背景となるプロダクトはこちらになります。
https://www.ai-shift.co.jp/5695

最後に

AI Shiftではエンジニアの採用に力を入れています!
少しでも興味を持っていただけましたら、カジュアル面談でお話しませんか?
(オンライン・19時以降の面談も可能です!)

【面談フォームはこちら】
https://hrmos.co/pages/cyberagent-group/jobs/1826557091831955459

AI Shift Tech Blog

Discussion