自社サービスにCopilot機能を組み込むためのOSS「OpenCopilot」入門
Copilot機能を組み込む時の選択肢になるかもしれないOSS、OpenCopilotについての記事です。
先にまとめ
- ユーザーが自然言語でタスクを指示できるインターフェースを提供するサービスが少しづつ増えてきている
- OpenCopilotは自社のサービスにCopilot体験を容易に実装するためのOSS
- 理由は不明だが
OpenCopilot is a free and open-source tool that allows you to create AI copilots for your SaaS product.
と書くなどfor SaaS推し
- 理由は不明だが
- UIコンポーネント・API連携・Flow機能・ドキュメント連携などが備わっていて、必要な機能を全て提供することを目指している
- 現状はベータ。将来の進化に期待
Copilot体験の増加
LLMの発展を背に、最近は「Copilot(or 自然言語インターフェース)」な機能を搭載する企業・サービスが増えてきており、自然言語を用いたヒューマン・マシンインターフェースの世界が少しづつ身近になりつつあるのを実感しています。
代表例はMicrosoft Copilot for Microsoft 365です。ユーザーの「◯◯やって」などの指示に基づいてエクセル上でタスクが実行される世界が描かれています。
何の新鮮さもない回答ですが、アプリケーション操作に習熟していなくても、様々な機能をハードル低く使いこなせる可能性があるのは大きな利点です。
MS以外の動き
Copilot/自然言語インターフェースに投資を始めているのはMicrosoftだけではありません。
例えば、ShopifyもSidekickを発表しています。
この機能もユーザーが自然言語で指示をして、Shopify内での操作やタスクをこなすことをサポートするものです。
また僭越ながら弊社の自然言語レポートも体験・思想としては近しい機能になっています。
エージェントと謳っていますが、その他にもAdept、LindyAI、Open Interpreterを代表とする自然言語でソフトウェアを操作・タスク指示する体験の勃興が続いています。
OpenAI Dev DayもAIエージェント時代の到来を予感させるようなコンテンツが盛りだくさんだったことは記憶に新しいです。
実装について
次にCopilotのような機能を自社アプリケーションへの組み込みについて簡単に考えてみます。
弊社の自然言語レポートの場合
先ほども触れましたが、僭越ながら弊社も自然言語からレポートを閲覧可能な機能を実験的に提供しており、体験・思想としては近しい機能です。
当時はFunction Callingも提供されていないタイミングだったため、LLMを用いてFunction Callingみたいな事が出来る仕組みを作って対応しました。
厳密にはSlot Fillingです。ある程度ユースケースが想定されている状況だったため、ユーザーの入力した情報から、ユーザーの意図を抽出し、それに応じた処理を裏側で実行することで実現しています。
今ならFunction Callingになるかもしれません。どちらにしてもfunction定義と実装を愚直にやれば実現はできますが、アプリケーション規模の大きさ・対応ユースケースの広さ次第で対応コストが嵩んでしまいます。
(仕様やUI/UXの工夫でだいぶ変わるとは思います)
Semantic Interpreter
実はMicrosoftから参考になりそうな論文が発表されています。
Semantic Interpreterと呼ばれるシステムに関する論文で、ユーザーが入力した指示をLLMで認識し、その指示に合わせてMicrosoft Officeを制御すると言う内容です。
詳細は割愛しますが、ざっくり以下のような流れで、ユーザー指示を元にLLMで専用DSLを吐き出し、そこからさらにアプリケーションに近いコードを自動生成するなど、学びになる取り組みが書かれています。
- ARM(Analysis-Retrieval Method)を用いて、ユーザーの指示やコンテキストを踏まえたプロンプトを構築
- 自然言語によるユーザーの指示をODSL(Office Domain Specific Language、Officeアプリケーションでアクションを実行し、コンテンツと対話するためのドメイン固有の言語)に変換
- ODSL ASTをネイティブアプリケーションAPI(Office-JS2など)で書かれたプログラムに変換し、アプリケーションによって実行
OpenCopilot
ようやく本題に戻ってきました。
OpenCopilotは自社のサービス(特にSaaSらしい)にCopilot体験を組み込むためのOSSで、この領域において興味深い選択肢になる可能性を秘めています。
やってくれることをざっくりまとめると、ユーザーの要求に基づいてAPIコールが必要かどうかをLLMが判断して、その結果に応じてAPIコール等を実施します。そしてそれらに必要なコンポーネント・仕組みをまとめて提供してるのが特徴です。
主な特徴
チャットUIコンポーネントの提供
テキストベースの指示を可能にするインターフェース・UIコンポーネントを提供します。
ユーザーが自然言語での質問や指示を通じて、タスクを依頼し、バックエンドシステムを呼び出し回答を行います。また設定等を行うダッシュボードも提供します。
提供されるUIコンポーネント:
Swaggerを用いたAPI連携
OpenCopilotはユーザーのリクエストを理解し、適切なAPIコールを行います。
APIコール先の設定はSwaggerファイルを用いて設定することが出来ます。
シンプルにUIからぽちぽち設定することも可能です。
複雑なワークフローに対応するためのFlow機能
前述のようにOpenCopilotはSwaggerファイルを用いて、リクエスト対象のAPIを連携・設定することが出来ます。
さらにFlow機能を使えば、複数のAPIコールを一つのフローとして扱うことが可能です。
セルフホスティングのオプション
セルフホスティングすることが可能で、データの完全なコントロールを得られることが強調されています。クラウド版の利用も可能です。
複数LLMモデルのサポートにも対応しています。
触ってみる
実際にダッシュボードから設定を行い、動かしてみます。
ただフォームエラーと表示されるが何がエラーなのかわからなかったり、ダッシュボードからは一度生成したCopilotのエンドポイントの追加や編集が出来ない、また削除も403で弾かれる。
デバッグする術がなく想定のエンドポイントにリクエストされない理由が辿れないなどとまだβなのを実感する状態ではありました。
(最後のもロードマップで、Traceability向上・LangSmith導入の計画はあるので追々改善される期待は持てます)
Copilotの作成
まずダッシュボードからCopilotを作成します。1Copilot = 1アシスタントのイメージです。
UIから設定する場合はフォームに入力します。
今回はユーザー情報の参照・更新を行うエンドポイントを立てて、それらのAPIを追加してみます。
登録が完了しました。
Copilotの設定
Copilotを一つ作成し終えました。
ダッシュボードでさらにいくつかの追加設定を行うことが出来ます。
context
AIアシスタントに渡すcontextの設定
Knowledge Base
Knowledge Baseの設定もできます
(しかしAdd Data Sourceから設定を試し、成功してそうだが、画面には現れず断念)
Flow
前述のFlowも簡易的に設定してみます。
チャットしてみる
チャットをする準備が整いました。提供されたUIコンポーネントを用いてアプリケーションに組み込む前に、ダッシュボードから試行することも可能です。
上記のように応答が返ってきます。
しかし肝心のプロフィール参照・更新依頼は残念ながら動作確認することが出来ませんでした...!
ざっくり内部の処理
ダッシュボードから試しましたが、想定のエンドポイントにはリクエストされませんでした。
デバッグも兼ねて軽くコードリーディングをしたので、OpenCopilotのllm-server(バックエンドAPI)のうち、ユーザーリクエストを元にChat/Copilot処理を行う部分を簡単に紹介します。
Chat/Copilot処理の流れ(抜粋)
-
ActionTypeの判定
- ユーザーのメッセージに基づいて行うべきアクションのタイプを決定
- メッセージの内容を分析し、適切なアクションタイプ(例:
ASSISTANT_ACTION
、KNOWLEDGE_BASE_QUERY
など)を返す
-
アクションタイプに基づく処理の分岐
-
ASSISTANT_ACTION
- API呼び出しやその他のアシスタント関連のアクションを処理
-
KNOWLEDGE_BASE_QUERY
またはGENERAL_QUERY
- 知識ベースからの問い合わせや一般的な問い合わせを処理
-
-
アクションタイプ別の処理
-
ASSISTANT_ACTION
の場合:- 現在のアプリケーション状態を処理し、Swaggerドキュメントを取得
- 既存のワークフローが存在するかを確認し、あれば使用して応答を生成
- 必要なAPI呼び出しを行い、応答を生成
-
KNOWLEDGE_BASE_QUERY
またはGENERAL_QUERY
の場合:- ベクトルストアを使用してチャット履歴と質問を元に適切な回答を生成
-
ActionTypeの判定
ユーザーの質問や要求がAPI呼び出し(ActionType.ASSISTANT_ACTION
)、知識ベースのクエリ(ActionType.KNOWLEDGE_BASE_QUERY
)、またはその他のカテゴリに属するかを判断・処理の分岐が行われます。
ActionTypeの判定は以下のような流れ・プロンプトが用いられています。
システムメッセージ:
"You possess the ability to categorize user input into predefined types determined by the user."
カスタム分類プロンプト:
"Respond with the string 'ASSISTANT_ACTION' for questions that are centered around data / API calling or questions related to math / data of an organization / API calls etc. Output 'KNOWLEDGE_BASE_QUERY' if and only if question can confidently be answered from the context provided in the chat."
ユーザーメッセージ:
"If the user is inquiring about a previous question, produce the same category as output as the one to which this follow-up pertains."
"If the question cannot be answered from the provided context output 'ASSISTANT_ACTION'"
ActionType.ASSISTANT_ACTION
の場合
本記事の本旨であるActionType.ASSISTANT_ACTION
の場合は、ユーザーの要求に応じたAPIエンドポイントの呼び出し、データベースからの情報取得等を行います。
プロンプトはいくつかの要素の組み合わせとなっており、以下の通りです。
LLMモデルがユーザーの要求を解析し、必要なAPIコールを特定するためのコンテキストと指示を提供します。
出力される応答は、適切なAPI操作のIDリストとボットメッセージを含むJSON形式で提供され、そのあとは必要に応じてAPIコールする処理が行われます。
システムメッセージ:
"You serve as an AI co-pilot tasked with identifying the correct sequence of API calls necessary to execute a user's action.
To accomplish the task, you will be provided with information about the existing state of the application and list of API summaries. If the user is asking you to perform a `CRUD` operation, provide the list of operation IDs of API calls needed in the `ids` field of the JSON.
`bot_message` should consist of a straightforward sentence, free from any special characters.
Note that the application uses current state as a cache, if you don't find the required information in the cache, you should try to find an API call to fetch that information. Your response MUST be a valid minified JSON."
以前の会話履歴(session_idを基に取得):
"User: How can I integrate your API into my website?"
"Bot: You can use our REST API to integrate it into your website."
現在のアプリケーション状態に関するメッセージ(current_stateが提供されている場合):
"Here is the current state of the application: [現在のアプリケーション状態の詳細]"
current_stateは、ユーザーのリクエストに基づいた適切な応答を生成するための追加情報として用いられます。slackやtrello向けのコードがデフォルトで存在していて、slackの場合はusersやchannleの情報を取得する実装となっています。
APIの概要に関するメッセージ:
"Here's a list of API summaries: [APIの概要リスト]"
応答フォーマットの指示:
"Reply in the following JSON format:
```{
"ids": [
"list",
"of",
"operation",
"ids"
],
"bot_message": "Bot response here"
}```"
ユーザー要求に関するメッセージ(user_requirement):
"[ユーザーの具体的な要求]"
使うメリット
ざっと触ってみてポジティブに感じた点です。
フルセットで提供されている
UIコンポーネント、ダッシュボード、バックエンドAPIの全てが提供されていて、究極フロントでコンポーネント組み込みだけ行えば実装が完結し得ます。
標準的な操作に対して「箱から出してすぐに使える」ソリューションの提供を目指しており、実装コストが抑えられる点は魅力です。
APIも提供されているのでUIコンポーネントだけ作るなども可能です。
SwaggerとFlow機能によるカスタマイズ性
OpenCopilotのメリットの一つは、SwaggerファイルでAPI連携の設定が完了して、Flow機能でユーザーの要求や特定の条件に基づいて、カスタマイズされたワークフローを設計できることです。
Parallel function callingも出来るようになりましたが、APIベースで色々組み合わせることが出来るのは嬉しさ・可能性がありそうです。
例えば公式サイトでは、カートのチェックアウトを複数のAPIで実現するシナリオが紹介されています。
Discussion