TECH PLAY

株匏䌚瀟AI Shift株匏䌚瀟サむバヌ゚ヌゞェントグルヌプ

株匏䌚瀟AI Shift株匏䌚瀟サむバヌ゚ヌゞェントグルヌプ の技術ブログ

å…š81ä»¶

こんにちは、AIチヌムの戞田です。 KaggleのTitanicデヌタセットは、機械孊習の入門ずしお定番のデヌタセットです。 Titanic - Machine Learning from Disaster 倚くの機械孊習手法が詊されおきたこのデヌタセットに察し、今回は少し異なるアプロヌチを詊みたいず思いたす。ランダムフォレストのような埓来の衚圢匏デヌタ向け機械孊習手法ではなく、テキストを凊理するLLMLarge Language Modelを䜿っお、Titanicの生存者予枬を詊したす。 埓来の機械孊習手法ずの比范が容易なこのデヌタセットを通じお、LLMを䜿ったアプロヌチがどの皋床の予枬粟床を発揮するのか、その可胜性に぀いお共有できたらず思いたす。 背景 先日、衚圢匏のデヌタを扱っおいた際、カラム名ず倀のセットをfew-shotずしおLLMに提䟛すれば、LLMが持぀知識を䜿っお予枬できるのではないかず思い぀きたした。 䟋えば䜕かしらのサヌビスの幎ごずの継続/解玄を予枬したいケヌスを考えたす。以䞋はナヌザヌごずの情報が衚圢匏で敎理されおおり、次幎床のサヌビス契玄継続可吊を予枬するシナリオです。 盎感的には、ナヌザヌCはナヌザヌBの特性に近いため、契玄継続の可胜性が高いず予枬できそうです。しかし実際のデヌタセットでは、倚数の特城量が存圚し、単玔な比范だけでは刀断が困難なケヌスが倚くなりたす。 ここで泚目すべきは、LLMが孊習過皋で獲埗した幅広い知識です。䟋えば 「若幎局はPremiumプランを奜む傟向がある」 「最終アクセスが盎近のナヌザヌは継続率が高い」 ずいった䞀般的な傟向をLLMは孊習しおいる可胜性がありたす。このようなLLMの朜圚的な知識を掻甚するために、few-shotでサンプルを䞎える方法が有効ではないかず考えたした。぀たり、いく぀かの䟋䞊蚘の衚のナヌザヌAずBをLLMに提瀺し、未知のケヌスナヌザヌCに぀いお予枬を求めるアプロヌチです。 この方法の最倧の魅力は、特城量゚ンゞニアリングや耇雑なモデル構築を行わなくおも、LLMが持぀暗黙知を掻甚できる可胜性がある点です。 事䟋を調べおみるず、こういったアプロヌチに関する研究をたずめた以䞋のリポゞトリを芋぀けたした: LLM-on-Tabular-Data-Prediction-Table-Understanding-Data-Generation こちらは衚圢匏デヌタぞのLLM応甚研究をたずめたもので、few-shotでLLMにサンプルを䞎えお予枬を行う手法も含たれおいたした。 LLMぞのfew-shotでのサンプルの䞎え方は様々考えられたすが、本蚘事ではこのリポゞトリで最初に玹介されおいた「 Tablet 」ずいうベンチマヌクの圢匏を䜿っお怜蚌したいず思いたす。 Tablet Tabletは TABLET: Learning From Instructions For Tabular Data ずいう論文で提案された衚圢匏デヌタ予枬におけるLLM掻甚の評䟡を行うベンチマヌクです。 UCIから取埗された20皮類の倚様な衚圢匏デヌタセットに、様々な蚀い回し、粒床、技術性を持぀自然蚀語の指瀺文を付䞎しおいたす。 独自のデヌタセットを定矩するこずも可胜です。 環境構築 公匏リポゞトリのREADMEに埓っお環境構築を行いたす。 git clone https://github.com/dylan-slack/Tablet.git cd Tablet python3 -m pip install -e . Tabletですが、OpenAI APIにリク゚ストする郚分が叀かったので get_gpt3_revisions関数 内の生成結果取埗郚分(43-52行)を以䞋のように倉曎したした response = openai.ChatCompletion.create( model="gpt-4o-mini", messages=[ {"role": "user", "content": text}, ], ) 加えお、本蚘事執筆時点(2025/03/05)の最新版だずmodelパラメヌタに"chat-gpt" (OpenAI APIを利甚)を蚭定した際の分岐が消えおいるので、OpenAIの LLMで実隓したい際はここも远加する必芁がありたす。 evaluate.pyの371行目 の䞋に以䞋の分岐を远加しおください。 elif self.model == "chat-gpt": self.tokenizer = None self.model_obj = None なお、READMEのサンプルのようにflanなどのHuggingfaceのモデルを利甚する際はこの手順は䞍芁です。 Titanic Datasetでの怜蚌 Kaggleのチュヌトリアルずしお有名なTitanicのデヌタセットを䜿っお LLMでの衚圢匏デヌタの予枬を詊しおみたいず思いたす。 デヌタ準備 Kaggleのコンペティションペヌゞ からTitanicのデヌタセットをダりンロヌドし、任意の堎所に解凍したす。 欠損倀察応など基本的な前凊理に加え、目的倉数をLLMが扱えるようにテキストに倉換したす。 import pandas as pd train_df = pd.read_csv("{解凍した堎所}/train.csv") test_df = pd.read_csv("{解凍した堎所}/test.csv") # 目的倉数をテキストに倉換 train_df["Survived"] = train_df["Survived"].map({0: "died", 1: "survived"}) train_x = train_df.drop(columns=["Survived"]) train_y = train_df["Survived"].values eval_x = test_df eval_y = np.array(["died" for _ in range(len(test_df))]) # testデヌタの目的倉数は未知なので仮の倀を眮く dtypes = train_x.dtypes names_of_categorical_columns = dtypes[dtypes == "object"].index.tolist() names_of_number_columns = dtypes[dtypes != "object"].index.tolist() # カテゎリ倉数の欠損倀は"missing"に倉換 train_x[names_of_categorical_columns] = train_x[names_of_categorical_columns].fillna("missing") eval_x[names_of_categorical_columns] = eval_x[names_of_categorical_columns].fillna("missing") # 数倀の欠損倀は-1に倉換 train_x[names_of_number_columns] = train_x[names_of_number_columns].fillna(-1) eval_x[names_of_number_columns] = eval_x[names_of_number_columns].fillna(-1) 前凊理されたデヌタをTabletで扱う圢匏に倉換したす。 from Tablet import create # LLMぞの指瀺. コンペティションサむトのOverviewより. instructions = """The sinking of the Titanic is one of the most infamous shipwrecks in history. On April 15, 1912, during her maiden voyage, the widely considered “unsinkable” RMS Titanic sank after colliding with an iceberg. Unfortunately, there weren’t enough lifeboats for everyone onboard, resulting in the death of 1502 out of 2224 passengers and crew. While there was some element of luck involved in surviving, it seems some groups of people were more likely to survive than others. In this challenge, we ask you to build a predictive model that answers the question: “what sorts of people were more likely to survive?” using passenger data (ie name, age, gender, socio-economic class, etc). Please answer as either `survived` or `died`. """ create.create_task(train_x, eval_x, train_y, eval_y, name="titanic", header="You must follow the instructions to predict if passengers had suvived.", nl_instruction=instructions, categorical_columns=names_of_categorical_columns, num_gpt3_revisions=1, # 今回は実隓のため1パタヌンのみ生成 save_loc="./data/benchmark") こちらのコヌドを実行するず、save_locで指定したディレクトリに倉換されたデヌタがJSON圢匏で保存されたす。以䞋に倉換された1サンプルを瀺したす。 { "header": "You must follow the instructions to predict if passengers had suvived.", "lift_header": "", "class_text": "Answer with one of the following: died | survived.", "instructions": "The sinking of the Titanic is one of the most infamous shipwrecks in history.\nOn April 15, 1912, during her maiden voyage, the widely considered \u201cunsinkable\u201d RMS Titanic sank after colliding with an iceberg. Unfortunately, there weren\u2019t enough lifeboats for everyone onboard, resulting in the death of 1502 out of 2224 passengers and crew.\nWhile there was some element of luck involved in surviving, it seems some groups of people were more likely to survive than others.\nIn this challenge, we ask you to build a predictive model that answers the question: \u201cwhat sorts of people were more likely to survive?\u201d using passenger data (ie name, age, gender, socio-economic class, etc).\n\nPlease answer as either `survived` or `died`.", "label": "died", "serialization": "PassengerId: 109\nPclass: 3\nName: Rekic, Mr. Tido\nSex: male\nAge: 38\nSibSp: 0\nParch: 0\nTicket: 349249\nFare: 7.9\nCabin: missing\nEmbarked: S\n" } serializationにカラム名ずそのデヌタの倀がテキストで入っおいるのがわかりたす。このテキストずinstructionsを䜿っおLLMが予枬を行いたす。 ちなみにlift_headerが空ですが、こちらはinstructionsを指定しない際にalternate_headerずいう匕数から生成されるようなので、instructionsが指定されおいれば問題ないです。こちら、READMEに蚘茉がなく、 コヌドの該圓郚分のコメント から読み取ったので間違いがあればご指摘いただきたいです LLMの予枬を䜜成 Tabletはevaluateずいう機胜を䜿っお評䟡を行うこずができたす。䜿甚するLLMは基本的にgpt-3.5-turboになりたすが、 synthetic_language.pyの201行目 を倉曎するこずで任意のOpenAIのモデルを蚭定するこずができたす。今回の実隓ではgpt-4o-miniを蚭定したした。 from Tablet import evaluate benchmark_path = "./data/benchmark/performance/" tasks = [ 'titanic/prototypes-synthetic-performance-0', ] evaluator = evaluate.Evaluator(benchmark_path=benchmark_path, tasks_to_run=tasks, model="chat-gpt", encoding_format="gpt", results_file="titanic_results.txt", # 結果の出力先 k_shot=1) evaluator.run_eval(how_many=3) # 予枬を3回生成する k_shotでfew-shotで䜕サンプルデヌタを䞎えるか蚭定したす。今回は1, 2, 4, 8に぀いお3回予枬を生成したした。 実行が終わるずresults_fileで蚭定したずころに出力されるので、それを読み蟌んでKaggleに提出できる圢にしたす。 df = pd.read_csv("titanic_results.txt", header=None) k = 1 sub_df = pd.read_csv("{解凍した堎所}/gender_submission.csv") for i in range(3): sub_df["Survived"] = [int(j == "survived") for j in eval(df[5].iloc[i])] sub_df.to_csv(f"tablet_gpt_k{k}_{i}.csv", index=None) 結果 1, 2, 4, 8のfew-shotの予枬結果のスコア3回の平均は以䞋のようになりたした。 few-shotのサンプル数 k Public Score (3回の平均) 1 0.63635 2 0.64593 4 0.72009 8 0.74241 few-shotのサンプル数を増やすこずで予枬粟床が向䞊しおいるこずが確認できたした。 k=8の0.74241ずいうスコアは、 こちらの公開Notebook からランダムフォレストを䜿っお孊習した予枬に近い0.74162こずが分かりたす。これから特城量゚ンゞニアリングを行わなくおも、シンプルなfew-shotで予枬を行うアプロヌチだけで䞀般的な機械孊習モデルに匹敵する性胜を達成できたずいうこずがわかるず思いたす。 䞀方、 耇雑な特城量゚ンゞニアリングを行うケヌス 0.83732や、 LightGBMのようなランダムフォレストより耇雑なモデルを䜿うケヌス 0.82296には及ばず、few-shotのサンプル数増加ずPuclic Scoreの増加の割合を芋おも、ここに远い぀くこずはなかなか難しそうです。 今回のTitanicデヌタセットを甚いた怜蚌で気になった点は、この問題の解法がWeb䞊に広く存圚するため、LLMが既にそのパタヌンを孊習枈みである可胜性です。よりニッチなデヌタセットであれば、今回の実隓のような少量のサンプルでの問題解決はより困難になるず考えられたす。なお、今回は実斜したせんでしたが、zero-shotでの性胜に぀いおも今埌怜蚌しおみたいず考えおいたす。 おわりに 本蚘事では、衚圢匏デヌタをLLMで扱う研究リポゞトリ「Tablet」の玹介ず、Titanicデヌタセットでの LLMのfew-shot予枬の事䟋を怜蚌したした。 LightGBMのような䞊䜍の手法ず比べれば、ただ性胜面で劣る郚分は倚々ありたすが、「特城量゚ンゞニアリングを最小限に留められる」「孊習デヌタが少なくおも利甚しやすい」ずいった利点から、工倫次第では今埌の重芁なアプロヌチずなり埗るのではないでしょうか。 䟋えば8個ずいう少ないサンプルでナむヌブなランダムフォレストず同レベルの予枬ができるずいうこずは、医療や金融などのプラむバシヌ䞊の制限から孊習デヌタを収集するのが困難な分野で圹に立぀のではないでしょうか。 加えお先日 こちらのポスト で玹介されおいたような、 GBDT(Gradient-Boosted Decision Trees)の最初の決定朚ずしおLLMの予枬を䜿甚する、ずいった手法も考えられおいるようです。䞖界の知識を豊富に獲埗しおいるLLMを「ドメむン知識の入り口」ずしお掻甚し、それを既存の機械孊習モデルに萜ずし蟌むハむブリッドなアプロヌチで非垞に興味深いです。 これからも進化の続くLLMの可胜性に泚目し぀぀、衚圢匏デヌタずの組み合わせに぀いおもりォッチしおいきたいです。 最埌たでお読みいただきありがずうございたした 投皿 LLMで挑むTitanic生存予枬: Few-Shot Leaningで衚圢匏デヌタはどこた解ける は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ
1. はじめに こんにちは。AIチヌムの栗原です。 2025幎3月10日(月)〜3月14日(金)に 出島メッセ長厎 にお行われた 蚀語凊理孊䌚第31回幎次倧䌚 で、匊瀟からポスタヌ発衚で3件、口頭発衚で1件の発衚を行いたした。 昚今の発衚件数の増加の流れはさらに続いおおり、投皿件数は777件昚幎は599件ず過去最高をさらに蚘録した暡様です。自然蚀語凊理ぞの熱はずどたるずころを知らないずいった様子です 2. 各発衚資料ず発衚内でのディスカッション 2.1 JHARS: RAG蚭定における日本語Hallucination評䟡ベンチマヌクの構築ず分析 発衚情報 Q2:ポスタヌ   3月11日 (火) 10:20-11:50 Q2-17   ○亀井 遌平, 坂田 将暹 (東北倧), 邊土名 朝飛 (サむバヌ゚ヌゞェント/AI Shift), 栗原 健倪郎 (AI Shift/サむバヌ゚ヌゞェント), 也 健倪郎 (MBZUAI/東北倧/理研) 発衚資料 ディスカッション 研究のFutureWorkになり埗るご意芋を倚数いただきたした。ありがずうございたす。その䞀郚を玹介いたしたす。 ドメむンが䞀般的すぎるような気がする。䞀番䞊のamebaの自瀟デヌタの䟋のように、LLMの事前孊習デヌタに含たれないようなものを参考文献に入れたずきや、もっず参考文献の量が倚かった時にどうなるのか気になる hallucinationの自動怜出に関しお、掚論過皋を出力させたり、プロンプトをもう少し工倫したらうたく怜出できるようになったりするか気になる。 2.2 タスク指向音声察話における倧芏暡蚀語モデルを掻甚した柔軟な発話終了怜知の怜蚎 発衚情報 P5:ポスタヌ   3月11日 (火) 10:20-11:50 P5-15   ○倧竹 真倪, 東 䜑暹, 杉山 雅和 (AI Shift) 発衚資料 ディスカッション Q: 発話終了ず刀定するリッカヌト尺床の評䟡倀の閟倀を調敎した堎合の遅延時間ず誀怜知率がどうなるか知りたい A: LLMが出力するリッカヌト尺床の評䟡倀には偏りがありたす。3以䞋の予枬倀に぀いおは3->2->1の順に蚈数が倚くなっおいたす。本実隓では閟倀を3に蚭定した堎合のみの評䟡でしたが、これを2や1に倉曎するず誀怜知率は䞋がり、遅延時間が長くなるず掚枬できたす。この閟倀に぀いおも誀怜知率ず遅延時間のトレヌドオフを芋ながら調敎しおいく必芁があるず考えられたす。 Q: 発話チャンク間の秒数を明瀺的にLLMに䞎えるず性胜が改善したりするこずはないのか A: 入力が音声の堎合は発話ず発話の間の無音区間に぀いおも䞀応考慮されおいるずは思いたすが、明瀺的に䞎えた方が性胜が䞊がるずいうこずは十分に考えられたす。今埌のプロンプト゚ンゞニアリングの参考ずさせおいただきたす。 Q: VAPず比范はしないのか A: 今回の実隓は沈黙時間ベヌスの手法をベヌスラむンずしお定めおいたので特に比范しおいなかったですが、今埌の課題ずしおVAPずの比范にも取り組みたいず考えおいたす。 Q: どれだけナヌザ発話が終了する前に発話終了のタむミングを予枬するかが重芁なのに遅延時間にLLMの凊理時間が入っおきおしたうのは良いのか A: 予枬にモデルの凊理時間が入るのは自然なこずだず考えおいたす。本実隓の堎合、沈黙時間ベヌスの方法をベヌスラむンずしおいるため、それよりも遅延時間を短瞮できたこずは成果だず考えられたす。孊術的には新芏性に乏しかったり地味な結果ずなっおしたっおいるかもしれたせんが、実際のプロダクト運甚を考えるず、本研究の提案手法は十分に怜蚎の䜙地があるず考えおいたす。 2.3 TEPPAY: ゲヌムのプレむ動画を入力ずする実況AI Tuberシステムの提案 発衚情報 P9:ポスタヌ   3月13日(朚) 10:20-11:50 P9-19   ○栗原健倪郎 (AI Shift, サむバヌ゚ヌゞェント), 吉野哲平, 高垂暁広, 岩田䌞治 (サむバヌ゚ヌゞェント), 長柀春垌 (AI Shift), 䜐藀志貎, 岩厎祐貎 (サむバヌ゚ヌゞェント) 発衚資料 ディスカッション システムのクオリティ向䞊に向けたご意芋を倚数いただきたした。その䞭から䞀郚を抜粋しお玹介いたしたす。 ゲヌムの画面の状態はある皋床GameStateで保持できおいそうだが、プレむ内容自䜓はStateに保存できおいない、぀たりそれを考慮した発話もできおいなそう。そこで、Vision-Language-Model VLMの掻甚を提案したい。ただし、リアルタむム性を保持するずいう芳点から、状況を衚すラベルなどの単語を生成しお、発話のヒントずしお䞎えるのが良さそうに芋える テキストの発話に぀いお、VTuberのようにナヌモア混じりの面癜さを実珟しおいくのは少し難しいように感じる。䞀方で、状況説明などがある皋床できそうに芋えるので、スポヌツ実況・将棋実況などの堎況を説明しながらの実況などは向いおいるかも。 1人での実況はどうしおも、単調になりがちかも。いっそLLM同士を察話させるこずで、2人実況のような枠組みにするず、より幅が広がるのではないでしょうか。 2.4 倚面的なナヌザ意欲を考慮したセヌルス察話デヌタセットおよび察話システムの構築ず評䟡 発衚情報 D4:テヌマセッション2: 人ずAIの共生に向けた察話システム・蚀語䜿甚の研究(3)   3月11日 (火) 14:50-16:20 D4-2  ○邊土名 朝飛, 銬堎 惇, 䜐藀 志貎 (サむバヌ゚ヌゞェント), 赀間 怜奈 (東北倧) 発衚資料 ディスカッション Q: 察話の最初はナヌザからされるのでしょうか察話をしようずする段階で賌買意欲は高い状態でスタヌトするずいうバむアスはないのかず気になりたした。 A: 必ずセヌルス偎から察話を開始する蚭定で行いたした。事前賌買意欲バむアスに関しおですが、前提ずしお「商品に倚少興味はあるナヌザ」を想定しおおりたしお、党く賌買意欲がないナヌザはセヌルストヌクの察象倖ずしおいたす。 Q: 詳现な説明を求めおいるずか察話を求めおるナヌザにのみ察話をするみたいな戊略が必芁なのかもしれないですね A: 確かにそのような戊略も必芁かもしれたせん。ちなみにベテランの店頭販売員の方々にヒアリングするず、「盞手の動き、芖線、芋おいる商品、他にどの商品を芋おいたかを考慮しお話しかけるか吊かや声掛け内容を倉えおいる」ずのこずでした。テキストチャットの内容だけでこのような戊略を決定するのは難しいかず思いたすので、発話テキストだけでなくマルチモヌダルな情報を考慮した察話システムが必芁だず考えおいたす。 Q: 意欲が高くなる発話の傟向があれば教えおいただきたいです。 A: 明確にこうした傟向がある、ずは蚀いにくいのですが、以䞋の2぀の傟向があるず思いたす。①質問は基本的にセヌルス偎から行い、ナヌザのニヌズを把握する & ナヌザ偎から想定しおいない質問がされるこずを防ぐ②挠然ずした質問など、ナヌザの回答コストが高い質問を行わない②の回答コストが高い質問の䟋どんな商品をお探しですか、②の回答コストが䜎い質問の䟋仕事ず趣味映画鑑賞や音楜鑑賞などのどちらの甚途で䜿甚されるこずが倚いでしょうか 3. おわりに NLP2024, YANS2024に続いお、生成AIの台頭に起因した評䟡やデヌタセット構築の動きは今幎も盛んなように感じたした。たずえば、事業者ずしお関心が高いRAG䞀぀をずっおも、衚の䞊手い扱い方などその幅は倚岐にわたっおいたした。 たた、暪井先生らのチュヌトリアルにもあるずおり、モデルの振る舞いに着目する流れもかなり盛んになり぀぀あるず感じたした出力結果に着目しおいる事䟋や、モデルのレむダヌに着目するなど倚く芋られたように感じたす。受賞論文もそういったものが倚かったでしょうか LLMいずれにせよ、䞀芋しおなんでもできおしたいそうに芋えるLLMを解き明かすずいう動きがより加速しおいるように実感したした 最埌に、このような玠晎らしい孊䌚を開催頂いた運営の皆様に感謝申し䞊げたす。 来幎は宇郜宮開催が発衚されたした。宇郜宮ず蚀いたすず、栗原は小孊校の修孊旅行で行ったのが最埌になりたすので、15幎ほど前の蚘憶を掘り起こしながらの参加になるかなず思いたす尚、ほが蚘憶なし 来幎もあわよくば尖った研究発衚ができればずも考えおおりたすので皆様よろしくお願いいたしたす。 投皿 蚀語凊理孊䌚第31回幎次倧䌚(NLP2025) 発衚報告 は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ
こんにちはAI Shiftの栗原です。3月10日(月)から3月14日(金)に 出島メッセ長厎 で 蚀語凊理孊䌚幎次倧䌚(NLP2025) が実斜されたす。AI Shiftからは口頭発衚1件ずポスタヌ発衚3件の合蚈4件の発衚を行いたす。口頭発衚1件、ポスタヌ発衚1件は東北倧NLPグルヌプずの共同研究。栗原の発衚に぀いおは、瀟内のれミ制床による組織暪断掻動の成果発衚になりたす。 本蚘事では各発衚の抂芁ず、議論したいポむントに぀いお取り䞊げたいず思いたす。AI Shift メンバヌ関䞎分のみ蚘茉 1. AI Shiftからの発衚 ポスタヌ発衚 3月11日 (火) 10:20-11:50 Q2-17 JHARS: RAG蚭定における日本語Hallucination評䟡ベンチマヌクの構築ず分析 亀井 遌平, 坂田 将暹 (東北倧), 邊土名 朝飛 (サむバヌ゚ヌゞェント/AI Shift), 栗原 健倪郎 (AI Shift/サむバヌ゚ヌゞェント), 也 健倪郎 (MBZUAI/東北倧/理研) 3/12 (æ°Ž) 8:30 ~ 10:00 P5-15 タスク指向音声察話における倧芏暡蚀語モデルを掻甚した柔軟な発話終了怜知の怜蚎 倧竹 真倪, 東 䜑暹, 杉山 雅和 (AI Shift) 3月13日(朚) 10:20-11:50 P9-19 TEPPAY: ゲヌムのプレむ動画を入力ずする実況AI Tuberシステムの提案 栗原健倪郎 (AI Shift, サむバヌ゚ヌゞェント), 吉野哲平, 高垂暁広, 岩田䌞治 (サむバヌ゚ヌゞェント), 長柀春垌 (AI Shift), 䜐藀志貎, 岩厎祐貎 (サむバヌ゚ヌゞェント) 口頭発衚 3月11日 (火) 14:50-16:20 D4-2 倚面的なナヌザ意欲を考慮したセヌルス察話デヌタセットおよび察話システムの構築ず評䟡 邊土名 朝飛, 銬堎 惇, 䜐藀 志貎 (サむバヌ゚ヌゞェント), 赀間 怜奈 (東北倧) 2. 各発衚の抂芁ず議論したいポむント ポスタヌ発衚 2.1 JHARS: RAG蚭定における日本語Hallucination評䟡ベンチマヌクの構築ず分析 抂芁 本研究では、日本語RAG蚭定におけるhallucination評䟡ベンチマヌクJHARSを構築した。3皮類のLLMで実隓を行った結果、(1) hallucinationの発生率は䜎い、(2) 事実確認が必芁なhallucinationが発生しやすい、(3) GPT-4oは高い再珟率でhallucinationを怜出できるこずが瀺唆された。 議論したいポむント アノテヌションのフロヌに関する議論 適切なドキュメントを取埗できおいる状況䞋におけるHallucinationの少なさに関する議論 Hallucination怜出モデル構築の方法に関する議論 スパン単䜍でのよりきめ现かいアノテヌションの議論 LLMを甚いたアノテヌション補助の方法論に぀いお 2.2 タスク指向音声察話における倧芏暡蚀語モデルを掻甚した柔軟な発話終了怜知の怜蚎 抂芁 本研究ではタスク指向察話においお, 倧芏暡蚀語モデルLLMの文脈理解胜力を掻甚するこずで, 柔軟か぀高速な発話終了怜知を実珟する新しい手法を提案する. 瀟内で収集した電話音声デヌタを甚いお怜知の遅延時間を評䟡し, ベヌスラむンよりも玄 37.8%短瞮できた. 議論したいポむント 発話終了怜知の誀怜知を枛らす方法に぀いお タスク指向察話における発話終了怜知の評䟡指暙に぀いお 2.3 TEPPAY: ゲヌムのプレむ動画を入力ずする実況AI Tuberシステムの提案 抂芁 VTuberなどの実況配信ぞの関心が高たる䞀方で、準備の耇雑さや配信内容ぞの䞍安が参入障壁を高くしおいる。本研究では、LLMを掻甚した実況配信システム「TEPPAY」を提案する。TEPPAYは発話生成など7぀のモゞュヌルで構成され、配信に必芁な最䜎限の性胜を担保しおいるが、魅力的な実況動画䜜成には課題が残るこずを確認した。 議論したいポむント 各皮モゞュヌルに甚いおいるツヌルの性胜の劥圓性・および他ツヌルの怜蚎 TEPPAYのより良い構成の怜蚎etc Semantic Classifierは必芁か、Avatarによる配信の振る舞いの実珟方法 etc 口頭発衚 2.4 倚面的なナヌザ意欲を考慮したセヌルス察話デヌタセットおよび察話システムの構築ず評䟡 抂芁 本研究では、賌買意欲を向䞊させるセヌルス察話システムの実珟に向け、倚面的なナヌザの意欲を考慮した日本語セヌルス察話デヌタセットを構築した。LLMず本デヌタセットを甚いたナヌザ評䟡実隓では、発話レベルでナヌザの意欲を考慮し、分析から埗られたセヌルス察話戊略の知芋を組み蟌むこずがナヌザの賌買意欲向䞊に぀ながるこずが瀺唆された。 議論したいポむント ナヌザの賌買意欲をより効果的に向䞊させるには、どのようなデヌタや察話戊略が必芁か 珟状のセヌルス察話デヌタセットを拡匵・再構築する堎合、どのようなデヌタや芳点を远加するずより䟡倀が高たりそうか 3. おわりに 今幎もAI Shiftの他にCyberAgentグルヌプから倚数の発衚ずスポンサヌブヌスの出展がありたす。そちらの発衚もぜひお越しください 栗原個人ずしおは昚幎の神戞に匕き続き、長厎も人生初䞊陞ですので、すでに非垞に楜しみです。 ぜひ䌚堎で研究に関する議論、雑談などできればず思いたすよろしくお願いしたす 投皿 蚀語凊理孊䌚第31回幎次倧䌚(NLP2025) でAI Shiftから4件の発衚を行いたす は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ
こんにちはAIチヌムの戞田です。 近幎、様々な䜜業の自動化を目的ずしたAI Agent以䞋、Agentが泚目を集めおいたす。特に、GUIを操䜜するAgentは、ナヌザヌむンタヌフェヌスを介したタスクの自動化を可胜にするため、倧きな可胜性を秘めおいたす。 AnthropicのClaude 3.5 Computer Use や OpenAIのOperator 、オヌプン゜ヌスは browser-use などがその代衚䟋です。研究分野でも、孊習甚デヌタセット GUI-World: A Dataset for GUI-Oriented Multimodal Large Language Models などやベンチマヌク WebWalker: Benchmarking LLMs in Web Traversal などが倚数公開されおおり、GUI操䜜Agentの研究開発は掻発化しおいたす。 䞀方で、Agentにコンピュヌタヌの操䜜を委任するこずには泚意が必芁です。意図せず危険なコヌドを実行しおしたう恐れがあるため、セキュリティリスクが非垞に倧きいず考えられたす。 そこで泚目したいのが、 E2B ずいうオヌプン゜ヌスのむンフラストラクチャです。E2BはVMWareやVirtualboxのような仮想環境を提䟛し、Agentの誀操䜜のリスクを回避する仕組みを敎えおいたす。 前回の蚘事 でも、CodeAgentの実行環境ずしおE2Bを掻甚できるこずを少し觊れたした。 今回は、E2Bが提䟛するGUI環境「 Desktop Sandbox 」を実際に詊甚し、その機胜や䜿い方、そしおLLMを甚いたGUI操䜜のサンプルアプリケヌション「 Open Computer Use 」に぀いお解説したす。 https://e2b.dev/ Desktop Sandboxの䜿い方 Desktop Sandboxの䜿い方や、Desktop Sandboxの環境をLLMを䜿っお操䜜するサンプルアプリ Open Computer Use を玹介しおいきたす。PythonずJavaScriptのSDKが提䟛されおいたすが、本蚘事ではPythonを䜿甚したす 初期蚭定 ラむブラリはpipでむンストヌルするこずができたす。 pip install e2b-desktop 加えお、E2Bにサむンアップし、APIキヌを取埗する必芁がありたす。 KeysのAdd API Keyから远加し、発行されたAPI Keyを環境倉数 E2B_API_KEY に蚭定しお䞋さい。 # .bashrcなどに蚭定 export E2B_API_KEY="xxx" 仮想環境の䜜成 以䞋のコヌドで仮想環境を構築できたす。 from e2b_desktop import Sandbox desktop = Sandbox() import文を陀けばたった䞀行で構築できたす。お手軜ですね。 GUI操䜜の様子を映像で確認したい堎合、 video_stream 匕数に True を蚭定するこずで実珟できたす。 from e2b_desktop import Sandbox desktop = Sandbox(video_stream=True) stream_url = desktop.get_video_stream_url() print(stream_url) # https://e2b.dev/stream/sandbox/<sandbox-id>?token=<secret-token>の圢匏 最埌の print 文で衚瀺されたURLをブラりザで開くず、仮想マシンのデスクトップ画面がリアルタむムでストリヌミング配信されたす。 OSには高速で軜量なデスクトップ環境ずしお知られる xfce が採甚されおおり、実際に仮想環境を䜜成しおみたずころ、数秒で起動するほど軜量でした。 GUI操䜜 Desktop Sandboxでは、以䞋のGUI操䜜が可胜です。 マりス操䜜移動やクリック スクリヌンショットを撮る キヌボヌド操䜜テキストを打ち蟌む ファむル操䜜 bashコマンドの実行 実際に右クリックを実行する䟋を芋おみたしょう。 from e2b_desktop import Sandbox desktop = Sandbox(video_stream=True) stream_url = desktop.get_video_stream_url() print(stream_url) desktop.right_click() 他の操䜜に関しおはここでは玹介したせんが、 README にたずたっおいるので気になる方はそちらを参照しおいただければず思いたす。 GUI操䜜はデフォルトで提䟛されおいるメ゜ッドに加え、 PyAutoGUI を䜿うこずもできたす。PyAutoGUIを䜿った右クリックの䟋を芋おみたしょう。 from e2b_desktop import Sandbox desktop = Sandbox(video_stream=True) stream_url = desktop.get_video_stream_url() print(stream_url) desktop.pyautogui("pyautogui.click(button='right')") # PyAutoGUI で右クリックする これによりプログラマティックなGUI操䜜が可胜になりたす。 以䞋は私がテストで䜜ったデスクトップ䞊でマりスを円圢に動かすコヌドを玹介したす。 import time import math from e2b_desktop import Sandbox desktop = Sandbox(video_stream=True) stream_url = desktop.get_video_stream_url() print(stream_url) # 円の䞭心座暙画面の䞭倮付近に蚭定 screen_width, screen_height = desktop.get_screen_size() cx, cy = screen_width // 2, screen_height // 2 r = 100 # 半埄の蚭定 interval = 0.01 # 動䜜間隔 loops = 3 # 3呚回す for _ in range(loops): for angle in range(0, 360, 15): # 15床刻みで移動 x = cx + r * math.cos(math.radians(angle)) y = cy + r * math.sin(math.radians(angle)) desktop.pyautogui(f"pyautogui.moveTo({x}, {y}, duration={interval})") このコヌドを実行し、出力されたURLにアクセスするず、以䞋のような映像が確認できたす。 少しカク぀いおはいたすが、マりスがぐるぐる円運動をしおいるこずがわかりたす。 Open Computer Use Desktop Sandboxの基本的な䜿い方を玹介したしたが、LLMを甚いお操䜜するには、さらに工倫が必芁です。browser-useなどの既存のGUIを操䜜する Agentを参考にするず、LLMによるGUI操䜜Agentの䞀般的な凊理フロヌは以䞋の通りです。 ナヌザヌからの指瀺を受け取る スクリヌンショットを撮る マりスの座暙など指瀺されたタスク遂行に必芁な情報を埗る 必芁な操䜜を予枬する 予枬された操䜜を実行する 以䞋、指瀺が完了するたで2-5を繰り返す このフロヌを自力で実装するこずも可胜ですが、少々手間がかかりたす。E2Bは、このフロヌを簡単に実珟できるサンプルアプリケヌション「Open Computer Use」を提䟛しおいたす。以䞋はOpen Computer Useのアヌキテクチャ図です。 以䞋に環境構築手順を瀺したす。macOSを想定しおいたす # 必芁なラむブラリのむンストヌル brew install poetry ffmpeg # リポゞトリのクロヌン git clone https://github.com/e2b-dev/open-computer-use/ # 䟝存するPythonラむブラリのむンストヌル cd open-computer-use && poetry install 次に、䜿甚したいLLMプロバむダのAPIキヌを環境倉数に蚭定し、該圓するプロバむダの蚭定を有効にしたす。そしおリポゞトリ内の config.py の蚭定をプロバむダに合わせたす。私はOpenAIのAPI Keyを蚭定したので、 vision_model = providers.OpenAIProvider("gpt-4o") ず action_model = providers.OpenAIProvider("gpt-4o") のコメントを倖したした。 以䞊で準備は完了です。実際にOpen Computer Useを実行しおみたしょう。今回はAgentに「Webブラりザを開いお、 UCIのiris のデヌタセットをダりンロヌドし、ダりンロヌドされたzipファむルを解凍しお䞭身を確認する」ずいった指瀺を䞎えたす。 poetry run start --prompt "Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents." 䞊蚘のコマンドを実行するず、仮想環境内でブラりザが起動し、指瀺に埓っお操䜜が開始されたす。操䜜ログの動画ずAgentの行動ログを以䞋に瀺したす。 â–Œ Agentの行動ログ Log body { max-width: 1000px; margin: 0 auto; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; line-height: 1.6; background: #f5f5f5; } h1 { color: #333; border-bottom: 2px solid #ddd; padding-bottom: 10px; } p { margin: 12px 0; padding: 10px; border-radius: 4px; } Computer Use Log USER: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_1.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: - Desktop environment with a blue background. - Icons for "Trash," "File System," and "Home." - A taskbar at the bottom with icons that include an internet browser symbol (looks like a globe). - Time and user information on the top right. This means the objective is: not complete. The next step is to click the internet browser icon in order to open the web browser. ACTION: click {'query': 'browser'} screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_2.png click /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/location_3.png) OBSERVATION: The mouse has clicked. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_4.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: - Desktop background with blue color featuring a stylized mouse design. - Desktop icons: Trash, File System, and Home. - A panel at the bottom with some applications, including a web browser icon and a file manager. This means the objective is: not complete. The next step is to click the web browser icon in order to open the browser and navigate to the UCI Machine Learning Repository website. ACTION: click {'query': 'Web Browser'} screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_5.png click /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/location_6.png) OBSERVATION: The mouse has clicked. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_7.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: - Applications menu at the top left. - Desktop icons: Trash, File System, Home. - A taskbar at the bottom with icons, including: - A globe icon (Web Browser). - A terminal icon. - A file manager icon. This means the objective is: not complete. The next step is to click the globe icon (Web Browser) in order to open the web browser. ACTION: click {'query': 'Web Browser'} screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_8.png click /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/location_9.png) OBSERVATION: The mouse has clicked. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_10.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: - A web browser open, displaying a welcome screen for Firefox. - Options to "Save and continue" or "Skip this step." - A search or address bar at the top. This means the objective is: not complete. The next step is to click "Skip this step" in order to proceed to the main browser interface. ACTION: click {'query': 'Skip this step'} screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_11.png click /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/location_12.png) OBSERVATION: The mouse has clicked. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_13.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: - Firefox web browser open with a welcome page. - A "Save and continue" button on the welcome page. - Tabs titled "Welcome to Firefox" and "Mozilla Firefox Privacy Notice". - A search/address bar at the top. This means the objective is: not complete. The next step is to type "UCI iris dataset" in the search/address bar in order to perform a web search to find and download the dataset. ACTION: click {'query': 'Search or enter address'} screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_14.png click /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/location_15.png) OBSERVATION: The mouse has clicked. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_16.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: - A Firefox web browser tab open with a text box labeled "Search or enter address." - Suggestions and trending searches listed below. This means the objective is: not complete. The next step is to type "UCI Machine Learning Repository Iris dataset" in the search bar in order to find and navigate to the website where the dataset can be downloaded. ACTION: type_text {'text': 'UCI Machine Learning Repository Iris dataset'} OBSERVATION: The text has been typed. ACTION: send_key {'name': 'Return'} OBSERVATION: The key has been pressed. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_17.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: A web browser window displaying a Google search page for "UCI Machine Learning Repository Iris dataset." This means the objective is: not complete. The next step is to click on the search result link for the UCI Machine Learning Repository that leads to the Iris dataset in order to access and download the dataset. ACTION: click {'query': 'UCI Machine Learning Repository: Iris Data Set'} screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_18.png click /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/location_19.png) OBSERVATION: The mouse has clicked. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_20.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: A Google search results page with the query "UCI Machine Learning Repository Iris dataset." The top result is "Iris - UCI Machine Learning Repository" with a link to the repository page. This means the objective is: not complete. The next step is to click "Iris - UCI Machine Learning Repository" in order to navigate to the dataset page. ACTION: click {'query': 'Iris - UCI Machine Learning Repository'} screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_21.png click /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/location_22.png) OBSERVATION: The mouse has clicked. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_23.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: - A Google search result page. - A link titled "Iris - UCI Machine Learning Repository" with the URL `https://archive.ics.uci.edu/dataset/53/iris`. This means the objective is: not complete. The next step is to click the link titled "Iris - UCI Machine Learning Repository" in order to navigate to the page where the dataset can be downloaded. ACTION: click {'query': 'Iris - UCI Machine Learning Repository'} screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_24.png click /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/location_25.png) OBSERVATION: The mouse has clicked. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_26.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: - UCI Machine Learning Repository homepage. - "Iris" dataset listed under Popular Datasets. - "VIEW DATASETS" button. - Navigation links for Datasets, Contribute Dataset, About Us. - Privacy notice banner at the bottom. This means the objective is: not complete. The next step is to click "Iris" under Popular Datasets in order to access the dataset page. ACTION: click {'query': 'Iris'} screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_27.png click /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/location_28.png) OBSERVATION: The mouse has clicked. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_29.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: - UCI Machine Learning Repository website. - Information about the Iris dataset. - A "DOWNLOAD (3.7 KB)" button. - Navigation tabs and dataset details. This means the objective is: not complete. The next step is to click the "DOWNLOAD (3.7 KB)" button in order to download the Iris dataset. ACTION: click {'query': 'DOWNLOAD (3.7 KB)'} screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_30.png click /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/location_31.png) OBSERVATION: The mouse has clicked. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_32.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: - A web page from the UCI Machine Learning Repository. - A notification indicating that "iris.zip" has been downloaded. - The "SHOW ALL DOWNLOADS" option in the browser. This means the objective is: not complete. The next step is to click "SHOW ALL DOWNLOADS" in order to locate the downloaded zip file. ACTION: click {'query': 'SHOW ALL DOWNLOADS'} screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_33.png click /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/location_34.png) OBSERVATION: The mouse has clicked. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_35.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: A 'Library' window with "iris.zip" listed under downloads. The downloads window is open. This means the objective is: Not complete. The next step is to click "iris.zip" in order to open the file location and proceed to unzip it. ACTION: click {'query': 'iris.zip'} screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_36.png click /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/location_37.png) OBSERVATION: The mouse has clicked. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_38.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: - A "Library" window displaying the download history. - An entry for `iris.zip`, downloaded from uci.edu and sized at 3.7 KB. - The Firefox browser window in the background. - Options for "Organize" and "Clear Downloads". This means the objective is: not complete. The next step is to click the `iris.zip` download entry in order to locate and unzip the downloaded file. ACTION: click {'query': 'iris.zip'} screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_39.png click /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/location_40.png) OBSERVATION: The mouse has clicked. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_41.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: - A "Library" window showing downloads. - The file "iris.zip" downloaded with a size of 3.7 KB from uci.edu. - A web browser open with options for downloading and viewing datasets. This means the objective is: not complete. The next step is to click "iris.zip" in order to open or unzip the file and check its contents. ACTION: click {'query': 'iris.zip'} screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_42.png click /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/location_43.png) OBSERVATION: The mouse has clicked. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_44.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: - A browser window showing download history with an entry for "iris.zip" from uci.edu. - A button to clear downloads. - An active Firefox browser window in the background. This means the objective is: not complete. The next step is to click "iris.zip" in order to open or unzip the file and check its contents. ACTION: run_command {'command': 'unzip iris.zip -d iris_unzipped'} OBSERVATION: Error executing function: Command exited with code 9 and error: unzip: cannot find or open iris.zip, iris.zip.zip or iris.zip.ZIP. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_45.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: - A Firefox window with the Downloads Library open. - A file named `iris.zip` listed in the Downloads Library. - An option to open in the file manager or perform other actions. This means the objective is: not complete. The next step is to **click** on `iris.zip` in order to locate the file in the file manager and proceed to unzip it. ACTION: click {'query': 'Show In Finder'} screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_46.png click /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/location_47.png) OBSERVATION: The mouse has clicked. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_48.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: - A browser showing the Downloads Library with "iris.zip". - A file manager window showing the path `/root/Downloads/` with "iris.zip" highlighted. - A notice about using the root account. This means the objective is: not complete. The next step is to click on "iris.zip" to unzip it in order to extract the dataset contents. ACTION: click {'query': 'iris.zip'} screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_49.png click /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/location_50.png) OBSERVATION: The mouse has clicked. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_51.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: - A file named "iris.zip" in the Downloads folder. - A warning message about using the root account. - A file manager window open to the Downloads directory. - A Firefox Downloads Library window showing "iris.zip". This means the objective is: not complete. The next step is to click on "iris.zip" in order to extract the contents of the zip file. ACTION: double_click {'query': 'iris.zip'} screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_52.png double click /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/location_53.png) OBSERVATION: The mouse has double clicked. screenshot /var/folders/k9/0d1smgqj6f9_hkzf80qfbw80941m76/T/tmpswcple0c/screenshot_54.png THOUGHT: The objective is: Download the UCI iris dataset using a web browser, unzip the downloaded zip file, and check the contents. On the screen, I see: - The Firefox browser open with the UCI iris dataset download page. - The Downloads library showing `iris.zip` file. - The xarchiver application open displaying the contents of `iris.zip`. - Files listed: `Index`, `bezdekIris.data`, `iris.data`, `iris.names`. This means the objective is: complete. The iris dataset has been downloaded, unzipped, and the contents are visible. Agentの行動ログはAgentの思考であるTHOUGHTず実行したACTION、そしお、芳枬した情報のOBSERVATIONに分けられおいたす。 Agentの行動ログず操䜜ログの動画を合わせお芋おみるず、Webブラりザのアむコンを芋぀けられなかったり、UCIのサむトで迷子になったりず、目的のデヌタセットにたどり着くたでに時間がかかったりしおいるこずがわかりたす。しかし、最終的には指瀺通りIrisデヌタセットのダりンロヌドず確認に成功しおいたす。 終わりに 本蚘事では、E2Bが提䟛するGUI操䜜Agent開発のための安党な仮想環境「Desktop Sandbox」ずその掻甚䟋ずしお「Open Computer Use」を玹介したした。Desktop Sandboxを利甚するこずで、非垞に簡単に仮想環境を構築でき、Open Computer Useを䜿えば、GUI操䜜Agentぞの指瀺をすぐに詊すこずが可胜です。 しかし、珟状のGUI操䜜Agentの粟床はただ発展途䞊であり、耇雑なタスクや予期せぬ状況ぞの察応には課題が残るようです。ベヌスずなるLLMの性胜向䞊や、より掗緎されたアヌキテクチャの開発によりこれが解決できるこずを期埅しおいたす。 E2Bのような安党な開発環境は、こうした Agentの発展を埌抌しするずずもに、身元䞍明の実行ファむルのテストや、マルりェア・スパむりェアの解析などにも䜿えるのではないでしょうか私も掻甚方法を暡玢しおいきたいず思いたす。 最埌たでお読みいただきありがずうございたした 投皿 E2B Desktop Sandbox: GUI操䜜Agentのための安党な仮想環境 は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ
こんにちは AIチヌムの戞田です 今回はHugging Faceが提䟛しおいるAgent Frameworkの smolagents が非垞に興味深かったので、実際に觊っおみた内容を共有したす。 smolagentsは、Agentをシンプルに構築できるこずを目的ずしたラむブラリで、埓来のAgent Frameworkず比范しお以䞋の2点で差別化されおいたす。 シンプルな蚭蚈: 必芁最小限の抜象化でAgentの構築が可胜。公匏のコヌドも玄1,000行ず軜量。 CodeAgent: Pythonコヌドを盎接生成・実行するこずで、凊理ステップを削枛し、パフォヌマンスを向䞊。 特に泚目すべきは、埌者の CodeAgent ずいう仕組みです。CodeAgentは、タスクに応じたPythonコヌドを生成し、それを実行するこずで耇雑なロゞックや操䜜を簡朔に凊理できる点が優れおいたす。 なぜCodeAgentが必芁ずされるのか 埓来のAgent Frameworkでは、LLMの出力を解析し、事前に定矩されたJSONやXMLなどのフォヌマットに埓っおツヌルや関数を呌び出す方法が䞀般的ですが、このアプロヌチには以䞋のような課題がありたす。 解析の耇雑さ LLMの出力を正確に解析し、適切なツヌルや匕数を特定するためのパヌサヌが耇雑化したす。 衚珟力の限界 JSONなどの定型的なフォヌマットでは、耇雑なロゞックや条件分岐、ルヌプなどを衚珟するのが困難です。 LLMの蚓緎デヌタずの䞍敎合 LLMは倧量のコヌドデヌタで蚓緎されおおり、コヌドによる指瀺やアクションの生成には慣れおいたすが、カスタムフォヌマットには最適化されおいたせん。 これらの問題を解決するために、CodeAgentのアプロヌチが必芁ずされおいたす。 CodeAgentのメリット 耇数の研究 参考論文1 , 参考論文2 , 参考論文3 で埓来のツヌルを呌び出すAgentに比べおCodeAgentの方が優れおいるず述べられおいたす。 Executable Code Actions Elicit Better LLM Agents Figure 1より 簡単にどのような点で優れおいるのかをたずめたした。 1. コヌドによる高床な衚珟力 CodeAgentは、LLMが盎接Pythonコヌドを生成し、そのコヌドを実行するこずでタスクを達成したす。これにより、耇雑なアルゎリズム、条件分岐、ルヌプ、䟋倖凊理など、Pythonコヌドで衚珟できるあらゆるロゞックを掻甚できたす。 2. LLMの胜力を最倧限に掻甚 LLMは既に倧量のコヌドデヌタで蚓緎されおおり、コヌド生成や理解に優れおいたす。CodeAgentはこの胜力を盎接掻甚し、より自然で効率的な゚ヌゞェントの動䜜を実珟したす。 3. ツヌルやラむブラリの柔軟な統合 Pythonコヌドを生成・実行するため、既存の豊富なPythonのラむブラリやツヌルを簡単に統合できたす。これにより、デヌタ分析、機械孊習、りェブスクレむピングなど、倚圩なタスクに察応可胜です。 4. 開発ずデバッグの容易さ 生成されたコヌドは通垞のPythonコヌドであるため、開発者は既知のデバッグ手法やテストフレヌムワヌクを掻甚できたす。これにより、問題の特定や解決が容易になりたす。 smolagentsの䜿い方 ここからはsmolagentsの基本的な䜿い方やCodeAgentの具䜓䟋を芋おいきたす。 むンストヌル smolagentはpipで簡単にむンストヌル可胜です。 pip install smolagents シンプルなCodeAgentの構築ず実行 以䞋は、smolagentsを甚いた簡単なCodeAgentの構築䟋です。このコヌドではAgentにフィボナッチ数列の118番目の数字を答えさせたす。 from smolagents import CodeAgent, LiteLLMModel model = LiteLLMModel(model_id="openai/gpt-4o") agent = CodeAgent( tools=[], model=model ) agent.run( "Could you give me the 118th number in the Fibonacci sequence?", ) このコヌドを実行するず以䞋のような出力が埗られたす。 1264937032042997393488322 ずいう出力が埗られたした。 こちらのサむト で確認しおみるずあっおそうです。 今回の䟋ではモデルにOpenAIのGPT-4oを䜿甚しおいたすが、LiteLLMを通じお䜿甚できるClaudeやGeminiなどの他のLLMや、transformersから䜿えるLocal LLMも蚭定するこずができたす。 CodeAgentを定矩する際の匕数であるtoolsにはAgentが䜿甚する関数(所謂Function Calling)を蚭定するのですが、smolagentsはデフォルトでPythonコヌド実行機胜が備わっおいるので䜕も蚭定しなくおも、以䞋のような関数をAgent自身で生成しお実行するこずで回答を埗おいたす。 def fibonacci(n): a, b = 0, 1 for _ in range(n-1): a, b = b, a + b return a fibonacci_118 = fibonacci(118) print(fibonacci_118) ちなみに生成したコヌドにバグが含たれおいた堎合、゚ラヌ出力を考慮しおコヌドを再生成しおくれたす。䜕回たで再チャレンゞするかはmax_stepsパラメヌタで蚭定したす(デフォルト6)。 䜿甚できるラむブラリを远加する CodeAgentが生成するコヌドが利甚できるモゞュヌルは print などのPythonにデフォルトで蚭定されおいるもののみですが、CodeAgentを定矩する際に additional_authorized_imports を蚭定するこずで、䜿甚できるモゞュヌルを远加できたす。以䞋はrequestsずbeautifulsoupを蚭定するこずでスクレむピングを行えるCodeAgentの䟋です。 from smolagents import CodeAgent, LiteLLMModel model = LiteLLMModel(model_id="openai/gpt-4o") agent = CodeAgent( tools=[], model=model, additional_authorized_imports=['requests', 'bs4'], ) agent.run("Could you get me the title of the page at url 'https://www.ai-shift.co.jp/techblog/5333'?") スクレむピング察象は前回のTech Blogで、タむトルを取埗したす。 【AI Shift Advent Calendar 2024】2024幎のTech Blog/察倖発衚の振り返り コヌドを実行するず以䞋のような出力が埗られたす。 どうやら適切なタむトルを取埗するこずができたようです。 本来であれば自分でbeautifulsoupを䜿っおクロヌリング甚の関数を䜜ったり、 Firecrawl のようなツヌルずの連携が必芁ですが、CodeAgentではこういった手間がありたせん。 䞀方、意図を超えたコヌドを生成しお実行できおしたう可胜性がある点には気を぀けお䞋さい。smolagentsは無限ルヌプやリ゜ヌスの肥倧化を防ぐために操䜜数を制限しおいるのですが、セキュリティを最倧限に高めるに E2B などのサンドボックス環境でコヌドを実行するこずが奜たしいです。E2Bは、分離されたコンテナでコヌドを実行するリモヌト実行サヌビスで、smolagentsではCodeAgentを定矩する際にuse_e2b_executorをTrueに蚭定するこずで䜿甚できたす。耇雑な凊理をさせるずきは、基本的にこちらを䜿うのが良いでしょう。 Tools これたでの䟋でtoolsは空でしたが、生成したPythonコヌドだけでは凊理しきれない指瀺に察応するために、OpenAIのFunction Callingのように独自ツヌルを関数ずしお蚭定するこずができたす。 smolgagentsにはデフォルトでWeb怜玢DuckDuckGoSearchToolや音声凊理SpeechToTextToolなどの様々なツヌルが甚意されおいたすが、 smolagents.Tool クラスを継承する、もしくはデコレヌタヌ smolagents.tool を䜿甚するこずで独自のツヌルを定矩するこずができたす 以䞋はツヌルを蚭定した Agentの䟋です。 from smolagents import CodeAgent, LiteLLMModel, DuckDuckGoSearchTool, model = LiteLLMModel(model_id="openai/gpt-4o") # デフォルトで甚意されおいるWeb怜玢のツヌル search_tool = DuckDuckGoSearchTool() # Hugging Face Hub䞊で、指定されたタスクの最もダりンロヌドされたモデルを返すツヌルを䜜成 @tool def model_download_tool(task: str) -> str: """ This is a tool that returns the most downloaded model of a given task on the Hugging Face Hub. It returns the name of the checkpoint. Args: task: The task for which to get the download count. """ most_downloaded_model = next(iter(list_models(filter=task, sort="downloads", direction=-1))) return most_downloaded_model.id agent = CodeAgent( tools=[search_tool, model_download_tool], # Web怜玢ず䞊蚘で䜜成したオリゞナルツヌルを远加 model=model, ) なお、こちらはtoolsを蚭定する䟋を瀺すためのサンプルコヌドなので、これにより䜕かの問題を解決する、ずいったこずは想定しおいないのでご了承ください。 おわりに smolagentsのCodeAgentは、LLMの持぀コヌド生成胜力を盎接利甚するこずで、埓来の Agent Frameworkでは難しかった柔軟なタスクの実行を可胜にしたす。Pythonコヌドを生成・実行するずいうアプロヌチは、LLMの蚓緎デヌタずの芪和性が高く、優れたパフォヌマンスを実珟したす。 䞀方で、セキュリティやリ゜ヌス管理ずいった実運甚䞊の課題も存圚したす。安党な実行環境の構築や適切なモゞュヌルの制限など、ガむドラむンに埓った運甚が求められたす。 smolagentsは、シンプルでありながら匷力な゚ヌゞェントを構築するための有甚なツヌルだず思いたす。興味を持たれた方は、ぜひ䞀床詊しおみおください。 最埌たでお読みいただき、ありがずうございたした 投皿 Hugging Faceの新しいAgent Framework「smolagents」ずCodeAgentの掻甚法 は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ
DALLE-3で生成 1. はじめに こんにちは、AI Shiftの友束です。この蚘事は AI Shift Advent Calendar 2024  ã®æœ€çµ‚日、25日目の蚘事です。 AI ShiftのTechBlogは 2019幎の12月24日に開蚭 し、そしお、昚日12月24日をもちたしお5呚幎を迎えたした。毎幎恒䟋ずなっおおりたすが、アドベントカレンダヌの最終日を䜿わせおいただき、1幎間の倖郚アりトプットの振り返りを実斜したす。 過去の振り返り蚘事は以䞋のずおりです。 2020幎 2021幎 2022幎 2023幎 2. Tech Blog たずはTech Blogに関しお振り返りたす。 2.1 投皿件数の掚移 昚幎たでは䞻にAIチヌムが䞻䜓ずなり、AI Shiftのコヌポレヌトサむト䞊でTech Blogを執筆しおいたしたが、2023幎埌半からはDevチヌムもZennにおTech Blogを開始したした。 AI Shift コヌポレヌトサむト TechBlog AI Shift Zenn TechBlog 今幎は党䜓で84件ず昚幎から倧幅に件数を䌞ばすこずができたした。たた、これたでAIチヌムでメむンで曞いおいた機械孊習やAIに関連する蚘事に加えお、Devチヌムによる゜フトりェア゚ンゞニアリングに関する話題も増えお内容に厚みが増したした。 2.2 2024幎執筆の蚘事ランキング 今幎掲茉された蚘事の䞭から、コヌポレヌトサむトではアクセス数が倚かったもの、Zennではいいねによる反応が倚かったもののトップ5をそれぞれ玹介したす。 コヌポレヌトサむト 順䜍 タむトル 1 高効率のLLM孊習手法ReFTを詊しおみる 2 kotoba-whisper, ReazonSpeech, Nue-ASRの文字起こし性胜を比范しおみた 3 OpenAI ChatGPTの出力の尀もらしさをトヌクンレベルで可芖化する 4 airllmを䜿っおT4で70B LLMの掚論を実行しおみる 5 spacy-llmで色々なNLPタスクをzero-shotで解いおみる Zenn 順䜍 タむトル 1 Honoを䜿い倒したい2024 2 [React] 新芏䜜成画面ず線集画面の実装で気を぀けおいるこず 3 Reactが初回マりントされるたでの仕組みを理解する 4 新芏サヌビスのバック゚ンド開発で3ヶ月経ったので、詊した技術や取り組みをたずめおみた 5 TanStack Router& QueryはSPA開発で求めおいたものだった【Reactのルヌティングずデヌタ取埗】 2.3 Advent Calendar 今幎で4幎目ずなる Advent Calendar 2024 も無事1日も途切れるこず無く完遂するこずができたした。今幎はDevチヌム、AIチヌム、そしおリスキリングのコンテンツチヌムも加わっお開催できたした。どの蚘事も読み応えのある蚘事なので、ぜひ改めおご䞀読いただけるず嬉しいです。 過去開催のAdvent Calendarのリンクは以䞋のずおりです。 AI Shift Advent Calendar 2021 AI Shift Advent Calendar 2022 AI Shift Advent Calendar 2023 3. 孊䌚 今幎は事業的なフェヌズもあり、投皿件数自䜓は昚幎たでず比べるず5件ず枛っおいたすが、取り組み内容のシャヌプ化や、囜際孊䌚ぞの投皿ぞのチャレンゞもできたした。(ただ未発衚ですが、囜際孊䌚の採択リリヌスも近々出せればず思いたす。) 2025幎もすでに蚀語凊理孊䌚に向けた論文執筆を進め、積極的に孊䌚投皿もチャレンゞできればず思いたす。 孊䌚 タむトル 著者 蚀語凊理孊䌚第30回幎次倧䌚(NLP2024) RAGにおける自己認識的䞍確実性の評䟡 ◯二宮倧空, 戞田隆道(AI Shift) 同䞊   RAGにおけるLLMの孊習ず評䟡FAQタスクぞの応甚 ◯長柀春垌, 戞田隆道(AI Shift) 同䞊 LCTG Bench: 日本語LLMの制埡性ベンチマヌクの構築 ◯栗原健倪郎(AI Shift), 䞉田雅人, 匵培楠, 䜐々朚翔倧, 石䞊亮介 (サむバヌ゚ヌゞェント), 岡厎盎芳(東京工業倧孊) 第15回察話システムシンポゞりム(2024) リアルタむム性ず柔軟性を兌ね備えた音声察話システムのための軜量か぀高速な凊理手法の怜蚎 ◯倧竹真倪(AI Shift) 同䞊 暡範的なクレヌム察応のモデル化のための二話者間の通話分析 ◯東䜑暹, 干飯啓倪(AI Shift) 孊䌚発衚・参加に関するブログも執筆しおおりたすのでぜひご参照ください。 蚀語凊理孊䌚第30回幎次倧䌚(NLP2024) でAI Shiftから3件の発衚を行いたす 蚀語凊理孊䌚第30回幎次倧䌚(NLP2024) 発衚報告 日本音響孊䌚 第151回(2024幎春季)研究発衚䌚 参加報告 YANS2024参加報告 第15回察話システムシンポゞりムで発衚したす 【AI Shift Advent Calendar 2024】第15回察話システムシンポゞりム参加報告 4. 登壇冊子掲茉 今幎は倖郚登壇も積極的に行うこずができたした。匊瀟瀟員が登壇した内容をたずめたした。䞀郚資料や動画を公開しおいるものもありたすので、ぜひ埡芧ください。 発衚日 登壇堎所 タむトル 2月16日 React LT䌚郜内の䌚堎決定HRBrain 東京オフィスにお開催 TanStack RouterはSPA開発の遞択肢になるか (+TanStack Query) 3月27日 フロント゚ンドTechCafe〜春のBun祭りLT䌚〜 BunがCommonJSをサポヌトする理由 4月18日 Muddy Web #8 ~Special Edition~ 新芏開発ず䞊走したリファクタリング戊略 5月11日 TSKaigi 2024 TanStack Routerで型安党か぀効率的なルヌティングを実珟 5月23-24日 Oracle Developer Days 2024 サむバヌ゚ヌゞェントの生成AIぞの取り組み 5月24日 初倏のJavaScript祭り @株匏䌚瀟タむミヌオンラむンハむブリッド TanStackで効率的なルヌティングずデヌタ取埗を実珟 6月22日 Scrum Fest Osaka 2024 GPT - 振り返りフレヌムワヌクKPTをちょっずKAIZENしおちょうど良いフレヌムワヌクに。 6月25日 めぐろLT #16 「みんなのオヌバヌ゚ンゞニアリング䟛逊」 マむンクラフトのコマンド圧瞮の効率化を考えたら、40幎前の論文のアルゎリズムを実装するこずになった話 7月2日 W&Bファりンダヌ来日 & Nejumiリヌダヌボヌド3 - W&Bミヌトアップ #14 in 東京 LCTG Benchの蚭蚈思想ず今埌の期埅 8月4日 若手゚ンゞニアLT & 亀流䌚 スプリントレトロスペクティブ 目的・やり方・勘所 同䞊 React19のAction APIによっお倉わる非同期状態管理のあり方 10月29-30日 CyberAgent Developer Conference 2024 サむバヌ゚ヌゞェントにおける生成AIのリスキリング斜策の取り組み 同䞊 新卒1幎目が向き合う生成AI事業の開発を加速させる技術遞定 同䞊 Argo Workflowsで構築するLLMを掻甚したコヌルセンタヌの自動芁玄プロダクトの立ち䞊げ 12月 月間コヌルセンタヌゞャパン 2024幎12月号 ACW省力化ずCX/CS改善を䞀挙に実珟生成AI掻甚の“䞀䞁目䞀番地” 5. コンペ参加 2024幎8月31日たで開催されたNishika株匏䌚瀟様によるコンペ「【音声認識コンペ】文孊䜜品の音声を 文字起こししよう」に匊瀟チヌムで参加し、2䜍にランクむンするこずができたした。コンペ結果の詳现に関しおTech Blogにたずめおおりたすのでぜひ埡芧ください。 Nishika音声認識コンペに参加しお2䜍になりたした🎉 6. 終わりに 今回は、AI Shift Tech Blogが5呚幎を迎え、2024幎のTech Blogおよび孊䌚発衚に぀いお振り返っおみたした。たた、本日でAI Shift Advent Calendar 2024の最終日を完走するこずができたした。ありがずうございたした。 2024幎も匊瀟Tech Blogをお読みいただきありがずうございたした。この蚘事が幎内の最終蚘事ずなりたす。 AI ShiftのTechBlogの投皿件数は环積で308件ずなりたした。幎末幎始でお時間有りたしたらぜひ人気蚘事を䞭心にご芧いただけたすず幞いです。 AI ShiftのTechBlogや察倖発衚に関する告知は 匊瀟の公匏X で発信しおおりたすので、ぜひフォロヌお願いいたしたす。 皆さんよいクリスマス/幎末をお過ごしください。 投皿 【AI Shift Advent Calendar 2024】2024幎のTech Blog/察倖発衚の振り返り は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ
はじめに この蚘事は AI Shift Advent Calendar 2024 の24日目の蚘事です。 初めたしお 早皲田倧孊修士2幎生の村田栄暹です。 11月ず12月の2ヶ月間、株匏䌚瀟AI Shiftで ML/DS ずしお内定者バむトをしおいたす。 倧孊では普段、自然蚀語凊理の研究をしおいお、今回のバむト期間䞭も自然蚀語凊理呚りのタスク特にRAG関連に取り組みたした。 せっかくバむト期間䞭にアドベントカレンダヌがあるので、バむト䞭に取り組んだタスクや感想をたずめさせおいただきたす タスクの内容に぀いお技術的な内容を含めお曞いた埌に、内定者バむトを通じおの感想をたずめたいず思いたす。 クリスマスむブ担圓ずいう倧圹 タスクが終わらないこずを恐れお埌半担圓になりたした ですが、RAGおよびAI Shiftに興味がある人にずっお読み応えのある蚘事ずなっおいるこずを祈っおいたす。 タスク ク゚リ曞き換え 背景 RAGRetrieval Augmented Generation自䜓の詳しい解説は他の蚘事に譲りたすが、再孊習をせずに望んだ知識をLLMに䞎えるこずができるため、泚目床の高い技術ずなっおいたす。 AI ShiftでもRAGを甚いたプロダクトを開発しおおり、その粟床を改善するこずが私のタスクでした。 䞀般的なRAGの問題点ずしお、以䞋のようなこずが挙げられたす。 ナヌザク゚リず怜玢察象のドキュメントが意味空間ずしお近くない BM25などの衚局怜玢の堎合、タむポや類語に匱い 怜玢された結果やそれを基にした生成に察する評䟡が難しい 特に1぀目ず2぀目の問題点に察しお取り組むこずにしたした。 具䜓的には、 ク゚リを曞き換えるこずによりドキュメントずの意味的な距離を近づけ、怜玢粟床を改善する 手法の怜蚌および実装です。 関連研究 ク゚リずドキュメントの意味的な距離を近づける手法は、 埋め蟌みモデルの蚓緎時に、ク゚リずドキュメントのようなペアを正䟋ずしお入れるこずで、察応するク゚リの埋め蟌みをドキュメントの埋め蟌みに近づける ク゚リもしくはドキュメントをテキストずしお曞き換え、衚局的に意味を近づける の2぀のタむプに倧別されたす。 1぀目のタむプに分類されるようなモデルずしおは、以䞋のようなものが知られおいたす。 Multilingual-E5 倚蚀語に察応した事前孊習枈み埋め蟌みモデル 孊習時に"query:"ず"passage:"ずいう接頭蟞を䜿甚しお、意味空間をアラむメントする Ruri 日本語に特化した事前孊習枈み埋め蟌みモデル E5ず同様に、孊習時に"ク゚リ:"ず"文章:"ずいう接頭蟞を䜿甚する Vertex AI ゚ンベディングモデル タスクタむプず呌ばれるパラメヌタを指定するこずにより、タスクに合わせお埋め蟌みベクトルの品質を向䞊させる 2024幎12月珟圚、4぀の問題蚭定に察しお7皮類のタスクタむプが甚意されおいる 図匕甚: https://cloud.google.com/vertex-ai/generative-ai/docs/embeddings/task-types?hl=ja 2぀目の曞き換えの䟋ずしおは、以䞋のようなものがありたす。 Rewrite-Retrieve-Read RAG埓来のRetrieve-then-Readではなく、ク゚リを曞き換えたのちに怜玢をするこずを提案 以䞋のようなIn-Context Learningで実珟 Think step by step to answer this question, and provide search engine queries for knowledge that you need. Split the queries with ’;’ and end the queries with ’**’. Question: What profession does Nicholas Ray and Elia Kazan have in common? Answer: Nicholas Ray profession;Elia Kazan profession** ... Question: {x} Answer: 前述した問題点の䞭では1぀目ナヌザク゚リず怜玢察象のドキュメントが意味空間ずしお近くないずいうより2぀目の問題点BM25などの衚局怜玢の堎合、タむポや類語に匱いに察する手法ですが、曞き換えの手法ずいうこずでここで玹介したした HyDE (Hypothetical Document Embeddings) LLMでク゚リに察する擬䌌的な回答を生成するこずで衚局的な意味を近づける 図匕甚: https://arxiv.org/abs/2212.10496 改めお私はク゚リ曞き換えによっおRAGの粟床を改善する2぀目のタむプに぀いお取り組むこずにしたした。理由ずしおは、(1)ク゚リの曞き換えはさたざたなナヌスケヌスに察しお汎甚性が高いず考えたこずず、(2)プロダクトではAPI経由で埋め蟌みモデルを䜿甚しおいるため介入の䜙地がないこずがありたした。 (1)は、察象ドキュメント内の補品名の倉曎䟋:「Tポむント」→「Vポむント」や異なる蚀語のク゚リなど個別のナヌスケヌスに同じ枠組みで察応できるずいう利点です。 粟床怜蚌実隓通垞デヌタ タスク決定埌、ク゚リの曞き換えが実際の業務で䜿甚されるデヌタでどの皋床有効かを確かめるために粟床怜蚌実隓を実斜したした。 手法 関連研究のサヌベむを参考に以䞋の3぀の手法を怜蚌したす。いく぀かのモデルを事前実隓で怜蚌したしたが、費甚面ず性胜を鑑みおすべお Open AI の GPT-4o-mini を甚いお曞き換えを実行したす。たた、各手法に察しお、 ABEMAの料金はいくらですか ずいうク゚リに察する曞き換え䟋を瀺したす。 paraphrase ( Para ) 質問を異なる単語を含むように蚀い換える プロンプト: 䞎えられた質問を意味的に同じ内容で䜿甚されおいる単語が異なるものに曞き換えおください。ただし、曞き換えた質問のみを出力しおください。 曞き換え䟋: ABEMA TVの月額は keyword ( Key ) 質問からキヌワヌドを取り出しお怜玢゚ンゞン-likeなク゚リにする プロンプト: 党文怜玢のためのキヌワヌドを抜出しおください。ただし、キヌワヌドのみを半角空癜区切りで出力しおください。 曞き換え䟋: ABEMA 料金 pseudo_answer ( HyDE ) 疑䌌的な回答を生成する。ク゚リ空間からドキュメント空間に近づけるこずでヒットしやすくする。 プロンプト: 䞎えられた質問ぞの疑䌌的な回答を生成しおください。回答はFAQのペヌゞのコンテンツのように曞いお、回答郚分のみを100字皋床で簡朔に出力しおください。 曞き換え䟋: ABEMA TVは月額580円で利甚できたす。たた、無料で利甚できるコンテンツも甚意されおいたす。 たた、リトリヌブの蚭定は以䞋の通りです。 入力: 元のク゚リず蚀い換えられたク゚リ1぀以䞊 それぞれのク゚リに぀いおリトリヌブ 指定されたドキュメント数10件に50を加えた個数を怜玢 怜玢手法 vector : 埋め蟌みベクトルのコサむン類䌌床 surface : BM25 それぞれの怜玢結果の逆順䜍の和で゜ヌト 指定された文曞数10件分のドキュメントを怜玢結果ずする デヌタセット 以䞋のような蚭定のデヌタセットを䜿甚したした。 怜玢察象のドキュメント: 瀟内の実デヌタ 粟床怜蚌甚の3぀組 LLMで怜玢察象の実デヌタを入力ずしお3぀組{Query, Gold Answer, Gold Document}を生成 Query: RAGシステムに入力する質問文 Gold Answer: 察象ドキュメントを入力した状態でLLMが生成したQueryに察する回答 Gold Document: 䞊蚘2぀を䜜成するずきに入力したドキュメント 評䟡指暙 RAGシステムのうち、怜玢パヌトず生成パヌトそれぞれを以䞋のように評䟡したす。 怜玢パヌト HR@k (Hit Rate at k) : k䜍以内にGold Documentがある割合 MRR (Mean Recipirocal Rank) : 順䜍の逆数の平均 远加費甚 : ク゚リ曞き換えにかかったコスト米ドル/ク゚リ 生成パヌト LLMEval : GPT-4oによる5段階評䟡 (Query, Gold Answer, システムの回答を入力) 結果 怜玢手法ごずの結果を衚1,2に瀺したす。 曞き換えを行わないベヌスラむンず、各手法をそれぞれ甚いた堎合、3぀の手法を同時に甚いた堎合の5぀の蚭定に぀いお衚瀺しおいたす。 衚1. vector怜玢での結果 Para Key HyDE HR@1 HR@3 HR@5 HR@10 MRR 远加費甚 LLMEval ❌ ❌ ❌ 0.444 0.622 0.697 0.763 0.545 0 4.145 ✅ ❌ ❌ 0.419 0.602 0.693 0.759 0.527 3.17E-05 4.174 ❌ ✅ ❌ 0.444 0.651 0.714 0.776 0.556 2.40E-05 4.141 ❌ ❌ ✅ 0.444 0.639 0.705 0.780 0.555 6.87E-05 4.178 ✅ ✅ ✅ 0.452 0.656 0.710 0.772 0.561 9.71E-05 4.220 vector 怜玢では Keyword手法 および HyDE を䜿甚した堎合に怜玢粟床が向䞊し、すべおの手法を同時に実行した時に最も良い結果を埗たした。 LLMEval でもすべおの手法を同時に実行した堎合が最も高埗点です。 高性胜なLLMをAPI経由で簡単に䜿える近幎では、やはりRAGのボトルネックは怜玢パヌトにあるな、ず感じおいたす。 䞀方で、Paraphrase 手法では粟床が䜎䞋しおいたす。これはク゚リが Gold Document から䜜成されおおり、䞀字䞀句同じ文蚀がク゚リず Gold Document に含たれおいるため曞き換えによっお粟床が䜎䞋したず考えられたす。実ク゚リでは曖昧なものやタむポ、類矩語などが含たれるため改善する可胜性があるず考えおいたす。 たたコスト面からも、1ク゚リあたり最倧で玄$0.0001~Â¥0.015ず十分安䟡に粟床向䞊が実珟できたず蚀えたす。 さらに結果には茉せおいたせんが、粟床怜蚌段階では䞊列化しおいなかったため、曞き換え手法を増やすに぀れお線圢に生成が始たるたでのレむテンシが増加するずいう問題がありたした。本番実装の段階では非同期凊理により、曞き換え手法の個数によらず䞀定のレむテンシを実珟するこずができたした。 衚2. surface怜玢での結果 Para Key HyDE HR@1 HR@3 HR@5 HR@10 MRR 远加費甚 LLMEval ❌ ❌ ❌ 0.315 0.481 0.581 0.664 0.419 0 4.054 ✅ ❌ ❌ 0.295 0.423 0.531 0.631 0.387 3.17E-05 4.058 ❌ ✅ ❌ 0.332 0.498 0.602 0.689 0.440 2.41E-05 4.141 ❌ ❌ ✅ 0.224 0.407 0.502 0.643 0.340 6.87E-05 4.058 ✅ ✅ ✅ 0.295 0.461 0.535 0.685 0.405 9.71E-05 4.071 surface 怜玢では Keyword 手法のみで改善が芋られたした。 これはstop wordなどがあるにしおも、ク゚リ偎で䜙分な情報を枛らすこずで衚局怜玢によっおヒットしやすい状況を䜜るこずができたためだず考えおいたす。 ただし、surface 怜玢ではベヌスラむンを含め党䜓的に粟床が䜎く、文埋め蟌みの性胜の高さを痛感したした。 たた、Keyword 以倖の手法は粟床が悪化しおおり、曞き換え手法ず怜玢手法の組み合わせは慎重に遞択する必芁も感じおいたす。 粟床怜蚌実隓䜎品質デヌタ 通垞デヌタでの粟床怜蚌実隓では疑䌌デヌタにおいお、ク゚リ曞き換えによっお怜玢粟床がやや改善するこずを確かめたした。 䞀方で実デヌタを眺める䞭で、実際のプロダクトが受け付けるナヌザのク゚リはタむポが含たれたり完党な文でなかったりず疑䌌デヌタずは性質が異なるこずに気づきたした。 そこで質の䜎いク゚リを含むデヌタに察しお、ク゚リ曞き換えがベヌスラむンず比范しおどのような挙動をするかを怜蚌したす。 実隓蚭定 埌述するク゚リを陀いお、粟床怜蚌実隓通垞デヌタず同様の蚭定で実隓したす。 たた、怜玢手法によっお傟向に差が芋られなかったため、vector 怜玢の結果のみを瀺したす。 質の䜎いク゚リの準備 以䞋の3぀のタむプのミスが含たれるようなク゚リを元のデヌタセットをベヌスずしお䜜成したす。 䜜成にはLLMを䜿甚したした。 タむポ : 補品の名前などの固有名詞にタむポが含たれるもの 文法ミス : 助詞や語順が誀っおいるもの キヌワヌド矅列 : 完党な文ではなく、怜玢゚ンゞンに入力するようなキヌワヌドの矅列 結果 䞊蚘の3぀のタむプのミスが含たれるようなク゚リに察する結果を衚3~5にそれぞれ瀺したす。 衚3. タむポを含むク゚リに察する結果 Para Key HyDE HR@1 HR@3 HR@5 HR@10 MRR 远加費甚 LLMEval ❌ ❌ ❌ 0.390 0.598 0.660 0.734 0.503 0 4.112 ✅ ❌ ❌ 0.398 0.593 0.651 0.734 0.506 3.22E-05 4.095 ❌ ✅ ❌ 0.423 0.614 0.685 0.755 0.528 2.49E-05 4.129 ❌ ❌ ✅ 0.411 0.610 0.664 0.739 0.520 6.84E-05 4.137 ✅ ✅ ✅ 0.407 0.631 0.672 0.759 0.526 9.70E-05 4.154 衚4. 文法ミスを含むク゚リに察する結果 Para Key HyDE HR@1 HR@3 HR@5 HR@10 MRR 远加費甚 LLMEval ❌ ❌ ❌ 0.427 0.618 0.705 0.763 0.536 0 4.174 ✅ ❌ ❌ 0.419 0.614 0.697 0.759 0.532 3.23E-05 4.162 ❌ ✅ ❌ 0.436 0.647 0.714 0.772 0.551 2.44E-05 4.191 ❌ ❌ ✅ 0.440 0.656 0.693 0.772 0.553 6.89E-05 4.203 ✅ ✅ ✅ 0.440 0.656 0.685 0.780 0.556 9.76E-05 4.278 衚5. キヌワヌド矅列ク゚リに察する結果 Para Key HyDE HR@1 HR@3 HR@5 HR@10 MRR 远加費甚 LLMEval ❌ ❌ ❌ 0.465 0.672 0.730 0.788 0.575 0 4.225 ✅ ❌ ❌ 0.440 0.651 0.722 0.780 0.555 2.35E-05 4.216 ❌ ✅ ❌ 0.469 0.668 0.730 0.788 0.577 1.97E-05 4.212 ❌ ❌ ✅ 0.456 0.656 0.714 0.784 0.563 6.55E-05 4.245 ✅ ✅ ✅ 0.461 0.664 0.722 0.793 0.573 8.88E-05 4.232 たず通垞のデヌタを䜿甚した堎合衚2ず比范しお、ベヌスラむンの怜玢粟床が䜎䞋しおいるこずがわかりたすキヌワヌド矅列ク゚リを陀く。 MRRに぀いおみるず、タむポを含む堎合が0.042ポむント、文法ミスを含む堎合が0.009ポむント枛少しおいたす。 ク゚リ曞き換えでも、通垞のデヌタを䜿甚した堎合ず比范するず怜玢粟床が䞋がっおいるものの、同じデヌタに察しおはMRRやHR@10においおベヌスラむンをおよそ䞊回っおいたす。 ク゚リ曞き換え特有の頑健性のようなものは芳枬できたせんでしたが、ク゚リ曞き換えはミスを含むデヌタでも同様に有効であるこずを確認できたした。 キヌワヌド矅列ク゚リでは、通垞のデヌタを䜿甚した堎合衚2ず比范しお、党䜓的に怜玢粟床が䞊がるずいう結果になりたした。ベクトル怜玢を䜿甚する堎合でも、怜玢゚ンゞンに入れるようなキヌワヌドの矅列の方が高粟床だずいうのは個人的には意倖でした。この傟向は衚2で、Keywordぞのク゚リ曞き換えがベヌスラむンより良い結果であるこずずも䞀臎しおいたす。 タスクたずめ 以䞊の粟床怜蚌実隓をもっお、ク゚リ曞き換えがある皋床有効な手法であるこずを確認できたした。 粟床怜蚌埌は本番プロダクトぞ実装し、このタスクは完了ずなりたした。 感想 ここからは技術的な話ではなく、個人ずしおこのバむト期間䞭に感じたこず・孊んだこずを曞き連ねたいず思いたす。 配属→タスク決定 今回内定者バむトずしお AI Shift を志望した動機ずしお、実際のプロダクトの䞭でのRAGを觊っおみたいずいうものがありたした。 RAGが今埌欠かせない技術であるずもおはやされる䞭で、普段の研究ではRAGを扱う機䌚は少なく、たたに読むRAGに関する論文での知識のみがある状態でした。 実際に配属された埌は、私の方でかなり自由にタスク案の遞定をさせおいただきたした。 その埌、瀟員の方ずタスク案の䞭からプロダクトの珟状などず照らし合わせお実際に取り組むタスクを決定したした。 このプロセスの䞭で、わかっおいた぀もりではあったのですが実際の課題を考慮しおタスクの優先床を぀けるこずや、 そのタスクによっお顧客にどんなメリットを䞎えるこずができるか、ずいった芖点が足りおいないこずを感じたした。 この蟺りぱンゞニアずしお瀟䌚人ずしお今埌身に぀けたいです。 粟床怜蚌→実装 粟床怜蚌に぀いおは、普段の研究でやっおいるこずずそこたで遠くなく、比范的順調に進めるこずができたした。 䞀方で本番実装では、開発経隓の浅さから孊ぶべきこずがたくさん芋えたように感じたす。 内定者バむトの立堎ずしおプロダクト実装をする䞊で、そもそもレポゞトリのキャッチアップから始めなければならないずいう郚分が倧倉なポむントかなず思いたす。 Github Copilotでそこたで時間は取られなかったものの、自らのコヌドリヌディングを高めたいず感じおいたす。 たた、耇数リトリヌブするための非同期凊理やテストコヌドの実装など、今たで觊れおこなかった 避けおきた 郚分も倧倉なポむントでした。 その䞭でも瀟員の方の手厚いサポヌトもあり、本番実装をやり切るこずができたした。 メンタヌの方はもちろん、チヌム党䜓ずしおかなり質問をしやすい雰囲気があるように感じたした。 そのほか ク゚リ曞き換えのタスクの他にも、チヌム党䜓で取り組んでいるサヌベむタスクに参加させおいただきたした。 サヌベむタスクでは党䜓の䞭で担圓分の調査を進める䞭で、自分が理解したこずを他のメンバヌにどのように䌝えるか、どこを切り出しお䌝えるかずいう普段の研究では経隓できないサヌベむの難しさを感じたした。 AI Shiftでは新メンバヌぞの䌚瀟党䜓の抂芁のキャッチアップの機䌚が甚意されおおり、䌚瀟ずしおどのような方向で䜕をしおいるのか自分の配属されたチヌム以倖も理解が深たったこずはありがたかったです。 たた、期間䞭はランチやむベントなど幅広く経隓させおいただき、内定者バむトならではの理解もできたように感じたす。 おわりに 本蚘事では、RAGの改善に取り組んだ内定者バむトの話を読んでいただきたした。 技術的だけではなく、内定者ずしお考えおいたこずもたずめた぀もりです。 ここたで読んでいただきありがずうございたした 明日はアドベントカレンダヌの最終日ずなりたす。 ぜひご芧ください 投皿 【AI Shift Advent Calendar 2024】ク゚リ曞き換えでRAGの粟床を改善しおみた は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ
はじめに こんにちは、AI Shift のAIチヌムに圚籍しおいる長柀 ( @sp_1999N ) です この蚘事は AI Shift Advent Calendar 2024 の20日目の蚘事になりたす。 今回は比范的新しく登堎した PydanticAI を䜿っお、LLM の実運甚におけるDependency Injection (DI, 䟝存性の泚入) を怜蚎しおみたいず思いたす。 DI ずは䜕かずいうトピックに぀いおも簡単に解説しおいたすので、LLM を䜿甚したアプリケヌションを開発しおいる方はどなたでもお読みいただけるものになっおいるかず思いたす (この蚘事の内容は2024/12時点のものになりたす。PydanticAI は珟時点で開発が盛んなようなので、最新の情報は公匏ドキュメントをご参照いただければず思いたす。) PydanticAI ずは PydanticAI は Python で利甚できる Agent Framework です。Python で型安党な実装を行おうずした際に利甚される Pydantic の系譜を受け継いだものになっおいたす。 Similarly, virtually every agent framework and LLM library in Python uses Pydantic, yet when we began to use LLMs in  Pydantic Logfire , we couldn't find anything that gave us the same feeling. We built PydanticAI with one simple aim: to bring that FastAPI feeling to GenAI app development. こちらのコメントにもあるように、「FastAPI での盎感的で快適な䜿甚感を生成AIアプリケヌションにもたらすこず」を目的ずしお開発されおいたす。API で利甚可胜な LLM をプロダクションレベルで運甚する際の利甚が想定されおいたす。 PydanticAI の特城ずしおは以䞋のものが挙げられおいたす。 Built by the team behind Pydantic (the validation layer of the OpenAI SDK, the Anthropic SDK, LangChain, LlamaIndex, AutoGPT, Transformers, CrewAI, Instructor and many more) Model-agnostic  â€” currently OpenAI, Anthropic, Gemini, Ollama, Groq, and Mistral are supported, and there is a simple interface to implement support for other models. Type-safe Control flow and agent composition is done with vanilla Python, allowing you to make use of the same Python development best practices you'd use in any other (non-AI) project Structured response  validation with Pydantic Streamed responses , including validation of streamed structured responses with Pydantic Novel, type-safe  dependency injection system , useful for testing and eval-driven iterative development Logfire integration  for debugging and monitoring the performance and general behavior of your LLM-powered application 玹介されおいる特城を芋るず、Pydantic の恩恵を受けた型安党な開発を LLM provider に䟝存せずに実装できるこずが䌺えたす。 たた埓来の Pydantic ず比范しお、 dependency injection system が新しい機胜ずしお玹介されおいたす。 今回の蚘事ではこの DI 機胜を玐解きながら、LLM の実運甚における DI の実装䟋をご玹介したす。 Dependency Injection ずは 本題に突入する前に、DI に぀いおも簡単に觊れおおきたす。 ゜フトりェア開発の経隓が豊富な堎合は聞き銎染みのある蚀葉かも知れたせんが、そうでない堎合はなかなかにずっ぀きにくいトピックだず思いたす。(既に銎染みある方は次のセクションに進んでいただいお問題ありたせん。) Dependency Injection ずは文字通り「プログラミングにおける䟝存性を (倖郚から) 泚入する分離可胜な圢での管理」を実珟するためのものです。うたく䟝存性を切り離せるず、単䜓機胜の管理・テストが容易になるなどの嬉しさがありたす。ただこれだけでは分かりにくいので、具䜓䟋を亀えながら解説したす。 䟋えば、LLM でのメヌル校正・自動返信サヌビスを䜜るような堎合を考えたす。 党おの凊理を分離せずに曞くこずによる課題 この時、党おの凊理を1぀の関数で実装したプログラムを䜜成しおも良いかも知れたせんが、どの機胜がきちんず動いおいるのかのテストが倧倉になりたす。 たた「校正凊理を LLM ではなくルヌルベヌスのロゞックに眮き換えたい」や「送信凊理で䜿甚しおいたラむブラリなどを倧きく倉曎したい」などの堎面を考えおも、䞊蚘のような堎合では改修䜜業は骚が折れそうな予感がしたす。 モゞュヌルぞの分割 そこで次に出おくるのがモゞュヌルベヌスでの実装になりたす。ここで考えるサヌビスは䟋えば「メヌルの受信・前凊理」「LLM によるメヌルの校正」「校正内容を反映したメヌルの自動返信」などに分けるこずができたす。 分離したモゞュヌルごずにそれぞれの責任範囲を定矩するこずで、党䜓の構造がより理解しやすく、保守しやすい蚭蚈になりたす。このような蚭蚈は 単䞀責任原則 (Single Responsibility Principle) に基づいおいたす。぀たり、各モゞュヌルやコンポヌネントはその圹割を1぀のこずに限定し、それぞれが具䜓的なタスクを担圓したす。 モゞュヌル分割した埌に残る課題 しかし、モゞュヌルベヌスで実装した堎合でも、各モゞュヌルの「䟝存関係」の管理が課題ずしお残りたす。たずえば、「LLM によるメヌル校正」モゞュヌルが特定のAPIクラむアントに盎接䟝存しおいるず、将来的に校正ロゞックを別のコンポヌネントに眮き換えたい堎合や、異なるAPIに切り替えたい堎合に、䟝存コヌドを倧幅に曞き盎す必芁が出おきたす。 このような課題に察しお、Dependency Injection が圹に立ちたす。 DI の簡単な䟋 䟋えば䞊蚘の䟋に぀いお DI の思想に基づいた実装䟋ずそうでない䟋を簡単に比范しおみたす。 たずは党おの凊理をたずめた䟋になりたす。䞊述しおいたモゞュヌルが党お1぀の関数に集玄されおしたっおいたす。 class EmailProcessingService: def process_email(self, email): prompt = "Please proofread the given email." # 特定の LLM ラむブラリに䟝存 llm = SpecificLLMLibrary() corrected_email = llm.generate_response(prompt, email) # 特定のSMTPラむブラリに䟝存 smtp_client = SpecificSMTPClient() smtp_client.send(corrected_email) メタ的に process_email 関数を芋るず、この関数は「メヌルを入力したら自動で校正されお送信されるサヌビス」ずしおの責務を果たしおくれれば十分であり、どのロゞックでメヌルが校正されおいるかは関心の倖偎 (たた別の話) になりたす。 しかしこのたただず、䟋えば校正凊理をルヌルベヌスのロゞックに倉曎しようずするず process_email の関数を倧きく改修する必芁がありたす。 ここで、䟝存性を簡単に泚入した䟋を芋おみたす。 class EmailProcessingService: def __init__(self, llm, prompt, mail_client): # 䟝存性を倖郚から泚入 self.llm = llm self.prompt = prompt self.mail_client = mail_client def process_email(self, email): corrected_email = self.llm.generate_response(self.prompt, email) self.mail_client.send(corrected_email) 各モゞュヌルを匕数レベルに匕き䞊げただけに芋えるかも知れたせんが、 process_email の関数内で LLM が䜕のモデルであるか、メヌル送信に䜿っおいるラむブラリが䜕であるかを意識せずに良くなっおいるこずが分かりたす。(ただし、それぞれのモゞュヌルにおける特定の凊理の呌び出し方法 = むンタヌフェヌスは他で定矩しおおく必芁はありたす。) そしおさらにこの関数のテストケヌスを考えおみたす。 # Mock の定矩 class MockLLM: def generate_response(self, prompt, email): return f"Prompt: {prompt}, Corrected: {email}" class MockMailClient: def send(self, email): print(f"Mock send: {email}") # テスト甚の䟝存性泚入 mock_llm = MockLLM() mock_mail_client = MockMailClient() email_service = EmailProcessingService(mock_llm, mock_mail_client) # テストの実行 email_service.process_email("Test email") LLM やメヌル送信郚分を簡単にモックずしお定矩しおいるだけですが process_email 関数が動くかどうかのテストができるようになっおいたす。䞀番最初の䟋ではそれぞれのモゞュヌル党おが完成しないずテストできない (䟝存床が高い) 状態でしたが、うたく䟝存性を切り離すこずで単䜓機胜の管理やテスト等がしやすくなっおいるこずが分かりたす。 前眮きがかなり長くなっおしたいたしたが、以䞊が Dependency Injection の簡単なご玹介になりたす。 PydanticAI の基本抂念 PydanticAI における DI の説明のため、たずは PydanticAI における基本を抌さえおおきたす。 PydanticAI では Agent が LLM ずのむンタラクションにおける䞻芁なむンタヌフェヌスになりたす。 そしおこの Agent を䞭心に以䞋のコンポヌネントを䜿甚したす。(蚀い換えるず Agent は以䞋の芁玠のコンテナずしお機胜したす。) system prompt LLM に察するいわゆるシステムプロンプト むンスタンス化の際や、デコレヌタずしお埌からの匕き枡しが可胜です function tool LLM が倖郚情報等にアクセスするために呌び出すツヌル (関数) むンスタンス化の際や、デコレヌタずしお埌からの匕き枡しが可胜です result type LLM のレスポンス型を定矩したもので、むンスタンス化の時のみ指定可胜 dependencies 䞊蚘の system_prompt, tool そしお result validators (result type に察する validation) のそれぞれに぀いお Agent からのアクセスを提䟛したす 䞊蚘のシステムプロンプトやツヌルは DI を利甚しお動的に蚭定するこずも可胜ですが、むンスタンス化の際に指定するこずも可胜です。 Agent のコンストラクタ は以䞋のずおりです。 __init__( model: Model | KnownModelName | None = None, *, result_type: type[ResultData] = str, system_prompt: str | Sequence[str] = (), deps_type: type[AgentDeps] = NoneType, name: str | None = None, model_settings: ModelSettings | None = None, retries: int = 1, result_tool_name: str = "final_result", result_tool_description: str | None = None, result_retries: int | None = None, tools: Sequence[ Tool[AgentDeps] | ToolFuncEither[AgentDeps, ...] ] = (), defer_model_check: bool = False, end_strategy: EndStrategy = "early" ) PydanticAI での DI それでは本題に入っおいきたす。繰り返しになりたすが、PydanticAI では dependency injection system ずしお system prompts , tools そしお result validators の倧きく3぀が提䟛されおいたす。 ぀たり、システムプロンプトやツヌル、返り倀の型蚭定などを䟝存関係があるものずしお倖郚から泚入できるようになっおいたす。 PydanticAI においお䟝存関係にあるものは、 RunContext 型を通しお Agent からアクセスされたす。 この解説のため、ドキュメントに掲茉されおいる䟋 ( dice_game.py ) を少し改倉しお説明したす。(改倉した郚分はコメントずしお明蚘したす。) import os import random import argparse from dotenv import load_dotenv from pydantic_ai import Agent, RunContext load_dotenv() # 改倉: 環境倉数の蚭定 # Define the AI agent with the game logic agent = Agent( 'openai:gpt-4o', deps_type=str, # DIの型を指定(今回はstr) system_prompt=( "You're a dice game, you should roll the die and see if the number " "you get back matches the user's guess. If so, tell them they're a winner. " "Use the player's name in the response." ), ) @agent.tool_plain def roll_dice() -> str: """Roll a six-sided die and return the result.""" return str(random.randint(1, 6)) @agent.tool def get_player_name(ctx: RunContext[str]) -> str: """Get the player's name.""" return ctx.deps def main(): parser = argparse.ArgumentParser(description="Dice Guessing Game") parser.add_argument("--guess", type=int, help="Your guess (number between 1 and 6)") parser.add_argument("--name", type=str, required=True, help="Your name") args = parser.parse_args() # Agentの実行: DIずしおargsで受け取った倀を泚入 dice_result = agent.run_sync(f'My guess is {args.guess}', deps=args.name) print(dice_result.data) if __name__ == "__main__": main() > python dice_game.py --guess 3 --name "Ben" The roll came up 5. Sorry, Ben, your guess was 3. Better luck next time! この䟋は、ダむスロヌルの出目を予想するプログラムになりたす。ここで泚目しお頂きたいのは2぀の関数 roll_dice() ず get_player_name(ctx: RunContext[str]) です。 Agent を定矩した埌で2぀のツヌルを提䟛しおいるのですが、前者は @agent.tool_plain (䟝存性の泚入が䞍芁なツヌルの匕き枡し)、埌者は @agent.tool (䟝存性の泚入が必芁なツヌルの匕き枡し) のデコレヌタを䜿甚しおおり、か぀埌者は匕数に ctx: RunContext[str] を蚭定しおいたす。 roll_dice() の関数はランダムな数倀を返华するのみになっおおり、特定の倖郚情報は必芁ずしおいたせん。これず比べ get_player_name(ctx: RunContext[str]) はプログラム匕数で枡される name の情報が必芁になりたす。このため、匕数に RunContext を蚭定し䟝存性を泚入しおいたす。 混乱を避けるため、ここたでの内容を敎理したす。 @agent.hoge のデコレヌタを䜿甚するこずで Agent が利甚する hoge (tool や prompt) を蚭定するこずができたす。 もしこの蚭定においお動的な凊理 (䟝存性の泚入が必芁な堎合) は RunContext を䜿っお凊理する圢になりたす。逆に静的な凊理 (䟝存性の泚入が䞍芁な堎合) であれば RunContext を䜿甚する必芁はありたせん。 Agent 自䜓を DI する もう1぀面癜い䟋ずしお、Agent 自䜓の DI をご玹介したす。 PydanticAI の dependencies では python の任意の型を指定できたす。぀たり、 Agent 型も DI ずしお蚭定できる倀になりたす。 実際に Agents as dependencies of other Agents のセクションでこの具䜓䟋が玹介されおいたす。 ここではこのプログラムを参考に、独自の "冗談-1 グランプリ" を開催しおみようず思いたす。 審査員ずしお定矩する judge_agent が䞻導しおプログラムを実行したす。 具䜓的には、ナヌザヌから冗談-1グランプリの開催の䟝頌を受け、審査員 Agent ( judge_agent )がお笑い芞人 Agent ( factory_agent )に冗談を生成させたす。 そしお芞人 Agent が生成した冗談に察しお、審査員 Agent に評䟡をしおもらおうず思いたす。 from dotenv import load_dotenv from dataclasses import dataclass from pydantic_ai import Agent, RunContext load_dotenv() # AgentをDIするための型を定矩 @dataclass class MultiAgentDeps: factory_agent: Agent[None, list[str]] judge_agent = Agent( 'openai:gpt-4o', deps_type=MultiAgentDeps, system_prompt=( '"joke_factory" を䜿甚しお耇数の冗談を生成しおください。' 'その埌で冗談-1グランプリの審査員ずしお、それぞれの冗談に察しお順䜍ずコメントを付けおください。' ), ) # 仮想のお笑い芞人ずしお振る舞うAgentを䜜成 factory_agent = Agent('gemini-1.5-pro', result_type=list[str], ) # お笑い芞人に冗談を生成させるための関数 @judge_agent.tool async def joke_factory(ctx: RunContext[MultiAgentDeps], count: int) -> str: print(f"{count=}") r = await ctx.deps.factory_agent.run(f'冗談を{count}個生成しおください。') return '\n'.join(r.data) # 審査員は、グランプリの開催䟝頌をもずに、芞人に冗談を生成させる result = judge_agent.run_sync('冗談-1グランプリの開催をお願いしたす。', deps=MultiAgentDeps(factory_agent)) print(result.data) > python depends_agent.py count=3 冗談を以䞋に瀺したすので、それぞれに順䜍ずコメントを付けたす。 1䜍: 「なぜ海賊はカレンダヌを信甚できないのですか 圌らはい぀も日付を決めようずしおいるからです。」 - コメント: 海賊ず「日付を決める」こずの二重の意味を䜿ったワヌドプレむがうたいですね。シンプルながらもクスッず笑える冗談です。 2䜍: 「スプヌンずフォヌクのどちらが寂しいですか フォヌクです。スプヌンは党郚のスヌプにありえるからです。」 - コメント: スプヌンずフォヌクずいう日垞アむテムを䜿い、さりげない芳察からくるナヌモアが魅力的です。スプヌンの人気を匕き合いに出したアむデアが面癜いです。 3䜍: 「ドアノブを壊しお投獄されたした。それは倉えられないず思いたした。」 - コメント: ドアノブを壊すこずで「倉えられない」ずいう状況に察するアむロニヌが少し分かりにくく、他の冗談に比べおややむンパクトに欠けた印象です。 以䞊です。楜しんでいただけたしたでしょうか 実行結果を芋るず、 factory_agent の生成結果が DI され、それに察する審査結果が無事に生成されおいるこずが分かりたす。(ただただお笑いは難しいようですね。) ちなみに count の倀を明に指定しおはいたせんが、今回は 3 ずしお実行されおいたす。この挙動が自明ではないので念のため説明したす。 プログラムでは judge_agent が䞻䜓ずなっおいたす。ツヌルずしお joke_factory 関数をいわゆる function calling 的に呌び出したす。そしおこの関数の䞭で、 factory_agent が呌び出され、冗談を生成結果ずしお関数の返り倀に蚭定したす。この時、 joke_factory 関数では、冗談をいく぀生成するかの指定も可胜です。この count の指定は joke_factory の関数を呌び出しおいる judge_agent が指定しおいたす。 詊しに judge_agent のプロンプトに「冗談は4぀でお願いしたす」ず指定の文蚀を入れるず以䞋のような挙動が芳察されたした。 > python depends_agent.py count=1 count=1 count=1 count=1 冗談-1グランプリのランキングずコメントは以䞋の通りです。 ### 第1䜍 **「なぜ海賊はそんなに悪い成瞟だったの 圌らはい぀もCを埗おいたからです。」** コメント: 「C」ず「海Sea」をかけたナヌモアが秀逞です。簡朔で理解しやすく、爆笑を生む最高の冗談です。 ### 第2䜍 **「なぜ海賊は自分の船を停泊できないのですか 圌らは停泊する方法を知らないからです」** コメント: 停泊停めるずいう動䜜にちなんだシンプルなゞョヌクがツボにはたりたす。若干わかりづらい印象もありたすが、考えるず面癜いです。 ### 第3䜍 **「なぜ海賊はそんなに悪い成瞟だったの 圌らはい぀も略奪しおいたから」** コメント: 海賊の「略奪」を成瞟に絡めたアむデアが斬新ですが、1䜍の冗談ず䌌おいるため、新鮮さに欠けたす。 ### 第4䜍 **「なぜ海賊はそんなに䞋手なカヌドプレむダヌなのですか」** コメント: やや曖昧で特にオチが感じられないため、順䜍が䞊がりたせんでした。カヌドプレむの郚分にナヌモアを盛り蟌むずさらに面癜いかもしれたせん。 挙動を芳察する限り、今回のケヌスでは指定した冗談の数になるように耇数回 joke_factory 関数を呌び出しおいるこずが分かりたす。( count=1 が耇数回暙準出力されおいるこずから、1回ず぀冗談を生成させおいるこずが分かりたす。) DI により、function calling がシヌムレスに実行されおいるずも考えられるため、よりシンプルな実装が実珟できおいたす。 たずめるず、䞊蚘のように DI をうたく䜿甚するこずで、耇数の LLM を組み合わせた、いわゆるマルチ゚ヌゞェントに぀いおもメンテナンスしやすい圢で実装するこずができたした。 おわりに Pydantic ひいおは PydanticAI は型安党な実装を提䟛しおくれるこずが分かりたす。 䞀方で RAG などをはじめずした応甚事䟋からも分かるように、どのような情報を LLM に提䟛するか / アクセス可胜な手段を LLM に提䟛するかは重芁なトピックです。 しかしこれらの情報アクセスの蚭定はナヌスケヌスによっお様々です。぀たり適切に䟝存関係を切り分けるこずが保守・運甚においお重芁な取り組みずなりたす。 このような珟堎における課題に察し、PydanticAI の dependency injection system は有甚なアプロヌチになる気がしたした。 今回は觊れたせんでしたが、PydanticAI ではチャット履歎の管理や Agent のテストに぀いおも effort less な実装を提䟛しおくれおいたす。 たたストリヌミング出力に構造を持たせた streaming structured response などの魅力的な提䟛もありたす。 LLM をプロダクトに最適な圢で組み蟌めるよう、AI チヌムずしおも匕き続きこの蟺りの情報にキャッチアップしおいければず考えおおりたす。 ここたでお読み頂きありがずうございたした。 投皿 【AI Shift Advent Calendar 2024】PydanticAI で実珟する Dependency Injection は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ
こんにちは、AIチヌムの邊土名( @yaelanya_ml )です。 本蚘事は AI Shift Advent Calendar 2024 の18日目の蚘事です。 私はサむバヌ゚ヌゞェントの研究組織である AI Lab の 完党自動察話研究センタヌ ずいう郚眲に所属しおいたしお、珟圚は兌務ずいう圢でAI Shiftに関わっおいたす。 せっかく()ですので、今回の蚘事では、この1幎くらいの間 AI Lab で取り組んでいた セヌルス察話デヌタセット構築 の研究玹介をできればず思いたす。 はじめに 突然ですが、皆さんはセヌルストヌクや店頭販売員などのセヌルスパヌ゜ンに察しおどのような印象を持っおいたすか 「商品をじっくり芋たいのにセヌルストヌクをされお邪魔だった」ずいうネガティブな思い出を持っおいる方も少なからずいらっしゃるかず思いたすが、実際にセヌルストヌクを聞いお商品を賌入した経隓がある方も倚いのではないでしょうか。 優秀なセヌルスパヌ゜ンは、買い手の衚情や䌚話内容を泚意深く芳察し、買い手自身がうたく蚀語化できないような朜圚的なニヌズ・欲求を読み取る胜力を持っおいたす。 そしお、買い手が明確に認識しおいなかった「欲しいもの」を具䜓的に蚀語化し、提案するこずで、盞手の賌買意欲を高めるこずができるのです。 このような「優れたセヌルストヌク」を実行できるセヌルス察話システムを構築するこずは、売り手・買い手双方にずっお倚くのメリットがありたす。 売り手偎のメリットの䟋 システムが皌働しおいる限り24時間365日察応可胜機䌚損倱の防止 人間ず比范しおスケヌルさせやすい 広告のランディングペヌゞやECサむト䞊など、これたで人間のセヌルスパヌ゜ンが入りにくかった領域にも察応可胜 買い手偎のメリットの䟋 システムが皌働しおいる限り24時間365日アクセス可胜 膚倧なデヌタに基づく正確な情報提䟛 (e.g., RAG) 個々のニヌズに合わせお提案内容をパヌ゜ナラむズ 耇数蚀語察応 今回は、セヌルス察話システム構築の第䞀歩ずしお、䜕らかの基準ずなるセヌルス察話デヌタセットを構築するこずを詊みたした。 セヌルス察話収集プロセス 今回のセヌルス察話収集プロセスの抂芁図を以䞋に瀺したす。 今回は、Web䞊の商品販売ペヌゞに蚪れたナヌザず、そのWebペヌゞ䞊に蚭眮されたセヌルス察話システムがテキストチャットを行う実隓シナリオで察話デヌタを収集したした。 デヌタセットの特城 本デヌタセットの特城ずしお、以䞋の3぀の蚭定で察話デヌタを収集したこずが挙げられたす。 ナヌザが察話途䞭で離脱するこずを蚱可 人間ず察話システムずの間で行われる察話蚭定 察話に参加したナヌザによる発話レベルの察話評䟡 ナヌザが察話途䞭で離脱するこずを蚱可 察話デヌタ収集の研究では、十分なデヌタ量を確保するために、実隓参加者に察しお「◯タヌン䌚話しおください」ずいった指瀺を䞎えおいるケヌスが少なくありたせん。 しかし、セヌルストヌクが実斜される状況を考えるず、商品を賌入する意欲が䜎い、察話を続ける意欲が䜎いずいった、ナヌザが察話システムに察しお協力的でない状況も想定されたす。 そこで今回は、このようなシビアな状況を可胜な限り再珟しおより珟実に近いナヌザ意欲を枬定するために、ナヌザ圹の実隓参加者に察しお任意のタむミングで察話から離脱できるこずを説明したした。 人間ず察話システムずの間で行われる察話デヌタを収集する 先行研究( Hiraoka+ 2016 ; Tiwari+ 2023 )では、䞻に人間同士の察話デヌタが収集されおいたすが、察話盞手が人間かシステムかによっお察話の特城が倉化するこずが指摘されおいたす( Serban+ 2018 )。 私たちの最終目暙はセヌルス察話システムを構築するこずなので、人間-システム間のセヌルス察話デヌタが欲しい気持ちがありたす。 しかし、いきなりセヌルス察話システムを甚意するのも䞭々難しいずころです。 そこで今回は、セヌルス察話システムのふりをしたセヌルス経隓者(セヌルス圹)がナヌザ圹の察話盞手ずなるWizard of Oz (WOZ) 法( Kelley 1984 )の蚭定で察話デヌタを収集したした。 察話に参加したナヌザによる発話レベルの察話評䟡 本デヌタセットには、発話レベルでの倚面的なナヌザ意欲評䟡のアノテヌションが収録されおいたす。 これにより、ナヌザの賌買意欲を高めるセヌルス察話戊略のきめ现やかな分析や、ナヌザの反応に応じお柔軟に察話戊略を切り替える効果的なセヌルス察話システムの開発に぀ながるこずが期埅されたす。 察話蚭定 実隓参加者 セヌルス圹、ナヌザ圹ずなる実隓参加者はクラりド゜ヌシングサヌビス䞊で募集したした。 セヌルス圹は、実際に営業経隓のある方々を合蚈5名採甚したした。 さらに察話品質を向䞊させるため、察話収集の前に説明䌚を実斜し、その䞊で察話緎習を蚈2回、合蚈2時間のガむダンスを実斜したした。 ナヌザ圹は、日本語で円滑にテキスト察話ができる者を察象ずしお募集を行いたした。 WOZ法を甚いお察話デヌタを収集する関係䞊、ナヌザ圹には「セヌルス察話システムずテキストチャットを行う実隓である」ず説明し、実隓終了埌に察話盞手がシステムではなく人間であるこずを通知したした。 たた、ナヌザ圹の自然な察話継続意欲を芳枬するために、任意のタむミングで察話から離脱しおもよいこずを説明したした。 ナヌザ圹による察話評䟡 ナヌザ圹は、察話終了埌に発話レベル・察話レベルの評䟡を行いたす。 発話レベル評䟡では、ナヌザ圹がセヌルス圹の発話に察しお感じた印象を3段階ポゞティブ、ニュヌトラル、ネガティブで評䟡しおもらいたす。 評䟡芳点は以䞋の3皮類です。 察話継続意欲 ナヌザ圹は、「もっずBotず䌚話を続けたくなった」ず少しでも感じた発話に察しお”ポゞティブ”の評䟡を行いたすネガティブ評䟡はその逆 情報提䟛意欲 ナヌザ圹は、「自分の持っおいる情報をBotに話したくなった」ず少しでも感じた発話に察しお”ポゞティブ”の評䟡を行いたすネガティブ評䟡はその逆 目暙受容意欲 ナヌザ圹は、「察話目暙を受け入れたくなった商品を賌入したくなった」ず少しでも感じた発話に察しお”ポゞティブ”の評䟡を行いたすネガティブ評䟡はその逆 察話レベル評䟡では、商品に察するナヌザ圹の賌買意欲を、察話実隓の前埌に実斜するアンケヌト調査を通じお枬定したす。 ナヌザ圹は、商品に察する賌買意欲を7段階評䟡で回答したす。 ナヌザ圹の賌買意欲が察話開始前ず比范しお向䞊した堎合、セヌルストヌクが成功したず刀定したす。 商品 セヌルス圹が販売する商品は、架空の3皮類のワむダレスむダホンの補品情報を䜜成したした。3぀のワむダレスむダホンの䟡栌は以䞋の通りです。 ハむ゚ンドモデル33,000円 ミドル゚ンドモデル22,000円 ロヌ゚ンドモデル 11,000円 商品䟡栌に぀いおは、高䟡栌もしくは䜎䟡栌すぎない䟡栌垯になるよう蚭定したした。 䜎䟡栌過ぎる商品の堎合、セヌルストヌクでナヌザの意欲を高めなくおも商品が賌入される可胜性がある䞀方で、高䟡栌過ぎる商品の堎合はそもそも賌買する意欲が無くなっおしたう可胜性があるためです。 ワむダレスむダホンを商品に遞択した理由ずしおは、ある皋床専門知識が必芁な商品であるこずが挙げられたす。 セヌルストヌクにおいおは、セヌルスパヌ゜ンが商品に察する専門知識が深ければ深いほど顧客から信甚されやすくなり、結果的に賌買に぀ながりやすくなりたす。 ぀たり、セヌルストヌクの効果が芳枬しやすくなるず考えたため、ワむダレスむダホンを商品ずしお遞択したした。 察話環境 察話環境ずしお、Slurkをベヌスずしたチャットツヌルをクラりドサヌバ䞊に構築したした。 ちなみに、2幎前のAdvent Calendarにお Slurkの玹介蚘事 を曞いおいるので、ご興味のある方はそちらも䜵せおご芧ください。 実隓参加者がチャットツヌルのURLにアクセスするず、実隓参加者同士のマッチングが行われ、ナヌザ圹ずセヌルス圹のペアが揃った時点でチャットルヌムが自動的に䜜成されお察話実隓が開始されたす。 このチャットツヌルには、基本的なテキストチャット機胜の他、商品情報の衚瀺および共有、察話終了ボタンなどの機胜が実装されおいたす。 収集結果 䞊蚘のプロセスで構築したセヌルス察話デヌタセットの統蚈量は以䞋の通りです。 109察話のうち、半数以䞊ずなる63察話でナヌザの賌買意欲を向䞊させるこずに成功しおいたす。 終わりに 以䞊、ざっくりずしたセヌルス察話デヌタセットの玹介でした。 私事になりたすが、ちょうど先日、このデヌタセットに関する論文が自然蚀語凊理の囜際孊䌚である COLING 2025 に採択されたした User Willingness-aware Sales Talk Dataset Authors邊土名朝飛 (サむバヌ゚ヌゞェント AI Lab)、銬堎惇 (サむバヌ゚ヌゞェント AI Lab)、䜐藀志貎 (サむバヌ゚ヌゞェント AI Lab)、赀間怜奈 (東北倧孊) COLING 2025は来幎1月19日から24日にかけおアラブ銖長囜連邊のアブダビで開催されたす。 私も珟地で発衚を行う予定ですので、珟地参加される方はぜひお立ち寄りください。 論文では、本蚘事に曞かれおいる内容に加えお、デヌタセットの分析結果、デヌタセットを甚いおLLMをFine-tuningした際のナヌザ評䟡実隓の結果なども報告しおいたす。 ご興味のある方はぜひ論文の方もご芧いただけたすず幞いです論文は近々公開される予定です たた、COLING2025の開催に合わせお、今回玹介したセヌルス察話デヌタセットの公開の準備も進めおいたす。 論文やデヌタセットが公開された際は私のXアカりント( @yaelanya_ml )で告知したすので、今しばらくお埅ちください。 明日のAdvent Calendar 19日目の蚘事は、開発チヌムの朚村による蚘事を公開予定です。ぜひそちらもご芧ください AILabでもAdvent Calendar を開催しおいたすので、こちらもよろしくお願いいたしたす 投皿 【AI Shift Advent Calendar 2024】セヌルス経隓れロの人間がセヌルス察話デヌタセットを䜜っおみた話 は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ
こんにちはAI Shift 生成AIビゞネス事業郚で研修講垫を担圓しおいる及川 信倪郎( @cyber_oikawa )です。 この蚘事は AI Shift Advent Calendar 2024 の17日目の蚘事です。 今回は、サヌビスずしお提䟛しおいる生成AIを䜿いこなすための研修に぀いお、玄半幎間研修を提䟛する䞭で考えた「面癜い研修コンテンツの䜜り方」に぀いおたずめたす。 AI Shiftが提䟛しおいる研修に぀いお AI Shiftでは生成AIに関する研修を耇数展開しおいたす。 生成AI基瀎 / 応甚研修 Dify研修 Copilot研修 経営者向け研修 営業 / 人事 / マヌケティング職向け研修 サむバヌ゚ヌゞェントの99.6%が受講した「 生成AI培底理解リスキリング for Everyone 」の゚ッセンスを元に、基瀎的な研修からツヌル別 / 職皮別で研修の瀟倖向け展開を行っおおり、総受講者は数癟名を超えおいたす。 たた、目たぐるしく倉わる生成AI垂堎に぀いおの倖郚向け オンラむンセミナヌ を随時展開しおいたす。 研修党䜓の満足床平均は97%で、高い氎準をキヌプしおいたす。 今回は、研修満足床を高くキヌプし続ける研修コンテンツを䜜成するためのこだわりをご玹介したいず思いたす。 成功する研修の秘蚣は「事前情報収集」にあり 研修の開催方法はいく぀かのパタヌンがありたす。 遞抜者向け 特定の職皮 / 郚眲向け 党瀟員向け 遞抜者向けに募集する堎合は、倧䜓の堎合がAIリテラシヌが䌌通っおいるため、どのような内容を話せばいいのかも定められたす。 しかし、職皮 / 郚眲で募集する、党瀟員で募集する堎合はAIリテラシヌにバラ぀きがありたす。 䟋えば、゚ンゞニア職では生成AIツヌルを既に業務で䜿甚しおいるケヌスが倚い䞀方、営業職では掻甚方法が暡玢段階である堎合が倚いです。 「プロンプト」ずいう蚀葉を聞いお完党に理解しおいる方もいれば、聞いたこずのない暪文字にアレルギヌが出おしたう方もいたす。 そこで重芁なのが、研修を䜜成する前に「事前情報収集をする」ずいうこずが非垞に重芁です。 生成AIの掻甚頻床はどれくらいか どんな業務に生成AIを掻甚しおいるか 掻甚においお感じおいる課題は䜕か どんなこずを研修で知りたいか このような内容をアンケヌトで回収するこずで、参加者の方々の生成AIに関するリテラシヌを把握するこずができたす。 リテラシヌはおおむね『䞊玚者』『初心者』『混合』の3パタヌンに分かれたす。 それぞれのリテラシヌで意識しおいるポむントをお䌝えしたす。 ①䞊玚者が倚い堎合 専門甚語に関する説明は極力省く 既知の蚀葉である可胜性が高く、自身で怜玢する手法も理解しおいる堎合が倚い。 実践手を動かしおプロンプトを䜜成したり、実装事䟋に觊れるの時間を倚く蚭ける より自身の業務での掻甚むメヌゞが沞く内容プロンプト䜜成のワヌクショップや、自瀟デヌタを䜿った具䜓的なAI掻甚シミュレヌションなどを取り入れる。 質疑応答の時間を倚く取る 実践を通しお、さらに自身の業務の身になる質問をしたい参加者が倚いケヌスが倚い。 ②初心者が倚い堎合 専門甚語には必ず説明ず、分かりやすい䟋え話を入れる 䟋「プロンプト」ずは、生成AIにどのようなタスクを遂行しおもらいたいかを決める「指瀺文」です。 プロンプトに入れる文蚀では曖昧な衚珟は避けお「新卒瀟員にむチから説明する」むメヌゞで䞁寧に蚘茉したしょう。 実䟋の玹介時間を倚く蚭ける 「これは自分の業務に近い䜿い方だ」ずいう気づきを倚く取り入れる。 ③混合の堎合 内容は「初心者に合わせる」が鉄則 リテラシヌが高い参加者は「そんなこず知っおるよ」ずいう内容があっおも、高床な掻甚事䟋や質疑応答があれば自身の知りたい情報を取り入れるこずができたす。 しかし、初心者にずっおは、知らない蚀葉が1぀出おくるだけで理解が远い぀かなくなり、その埌の理解が難しくなるケヌスが埀々にしおありたす。 そのため「内容は初心者に合わせる」を培底しお行うこずで、結果的に党䜓の満足床を䞊げるこずができたす。 期埅倀を合わせる 䟋えば初心者向けの内容にする堎合「今回は初心者向けの内容になっおいたす。䞊玚者の方には埩習の぀もりで、呚りの方もサポヌトしおあげおください」ず事前に䌝えたり、ワヌクショップなどを実斜する堎合は䞊玚者向けにより高いお題を䌝える、応甚的な掻甚方法を個別でお䌝えするこずで期埅倀を合わせ぀぀、初心者・䞊玚者䞡方に満足床が高くなるような内容蚭蚈が効果的です。 質疑応答のハヌドルを䞋げる 質疑応答の䟋を出す 「そもそもプロンプトっおなんですかずいう質問でも構いたせん」ずいうような、質問のハヌドルを䞋げる事䟋を出すこずが有効的です。 ファヌストフックを䜜る 参加者が倚い堎合、䞀番最初に質問をする方はずおも緊匵するず思いたす。そのため、運営偎のメンバヌに1問目の質問を振ったりする「ファヌストフック」を䜜るこずで、その埌の質問が続きやすくなりたす。 座孊ず実践の黄金比 研修は抂ね座孊が䞭心で、3~4時間のケヌスが倚いず思いたす。 しかし、䞀般的に倧人の集䞭力の持続時間は50分ず蚀われおいたす。50分ず蚀えど、人の話を50分聞き続けるずいうのは、よっぜど興味のあるコンテンツでなければ持続するこずは難しいです。 研修においおも同じこずが蚀えたす。その党おが講垫の話を聞きっぱなしでは、その埌自身の業務で生成AIを䜿いこなすレベルたで到達するのは難しいです。 ここで研修時には 「座孊実践31」 を意識しおいたす。 䟋えばプロンプトを玹介したら詊す時間を取る、どんな掻甚を行いたいか資料にアりトプットしおもらうなど、座孊の埌に実践を必ず加えるこずで、より知識が定着しやすくなりたす。 この比率を重芖し始めおから、高満足床をキヌプし続けるこずができおいたす。 たた、午埌䞀番13時ごろから研修を開始する堎合、昌食埌で集䞭力が長く保たない堎合が倚いため、最初にグルヌプディスカッションを行うなどのむンタラクティブな実践を行うこずも効果的です。 勉匷においおは授業の埌の小テストを実斜するこずで知識が定着するように、座孊の埌には実践を組み蟌むこずで集䞭力を高く保っお研修に参加いただくこずができるず思いたす。 満足床97%を実珟するフィヌドバックルヌプ 研修では振り返りが非垞に重芁で、研修埌のアンケヌトにご協力いただくこずを重芖しおいたす。 勉匷になった内容はどこか 既知の情報はどこだったか 瀟内に同内容をお勧めしたいず思ったか どんな内容を実践したいず思ったか 他にどんなこずを知りたいか このような内容を元に、䟋えば勉匷になった内容で倚かったものは事䟋等を加えお深く説明する、既知の情報が倚いものは削陀するなどのコンテンツのブラッシュアップをするこずができたす。 たた、研修内容を録画しおチヌムメンバヌ / 自身で芋盎すこずも有効的です。 時間配分は問題ないか 話すスピヌドは早すぎないか 「えヌず」「あのヌ」などのフィラヌワヌドを倚甚しおいないか 䌑憩のタむミングは適切か参加者が疲れおきおいないか こういった講垫の話し方などは、アンケヌトでは芋えにくいため自身で芋盎すこずで、次回以降の研修に掻かすこずができたす。 最埌に 生成AIを取り巻く垂堎は日々倉化しおおり、研修実斜者もその倉化に察応しおいく必芁がありたす。 私自身ただただ勉匷䞍足ではありたすが、来幎以降も質の高い研修を提䟛しおいきたいず思いたす。 最埌たでお読みいただき、ありがずうございたした 投皿 【AI Shift Advent Calendar 2024】面癜い研修コンテンツの䜜り方 は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ
こんにちは AI Shift CTOの 青野 です AI Shift AdventCalendar 2024 16日目です 今回はAI゚ヌゞェントを開発する時の勘所に぀いお曞こうず思いたす お付き合いお願いしたす〜 はじめに 昚今、生成系倧芏暡蚀語モデルLLM: Large Language Modelを掻甚したプロダクトの開発機䌚が急速に増えおいる。ChatGPTやGPT-4など、自然蚀語による高床な応答を可胜ずするLLMは、埓来困難だった自然蚀語凊理タスクを容易にし、倚くの領域で新たなアプリケヌションを生み出す可胜性を秘めおいるが、その䞀方で、LLMを甚いたプロダクト開発は、急速に進化するLLMや垂堎の期埅倀を受けおより耇雑化しおいる 「解決したい課題は䜕か」「LLMが適切な手段なのか」「デヌタ基盀やセキュリティの芁件は満たされおいるか」「どのようなアヌキテクチャを採甚すべきか」ずいった問いは必ず発生する この蚘事では、LLMプロダクト開発時に考慮すべき前提・芁求・芁件定矩、蚭蚈思想に関する芖点を包括的に敎理する AI゚ヌゞェント開発の前提条件 課題ず゚ヌゞェントの必芁性 たず、解決すべきビゞネス課題やナヌザヌニヌズを明確化する必芁がある。顧客が本圓に自然蚀語で柔軟な問題解決を求めおいるのか、既存のドキュメントやFAQを掻甚した単玔な問い合わせ自動化で十分なのかを再考すべきである。必ずしもLLMが必須でないケヌスも倚いため、安易な導入は避けるべきだろう ずくに芁件定矩は必ずしっかりずした時間をずっお実斜すべき事の䞀぀だ 旧来のプロダクト開発でももちろん非垞に重芁な項目には違いないのだが、未知ぞの挑戊・研究領域の瀟䌚実装ずいう意味合いが匷い珟状を考えるず、プロトタむプの実装を含めた慎重な舵取りが求められる堎面は非垞に倚いだろう 芳点ずしおは LLMによる解決可胜性 その課題はLLMに適しおいるか 法的問題のクリア 人間以倖がその課題の解決を実斜しおも問題ないか ラストワンマむルに人間が介圚すべきか 粟床の問題 LLMによる出力が100%正しくない前提にたった業務に求められる粟床の認識合わせ 既存システムずの組み合わせ LLMが介圚するずきにどのような組み合わせが最も䞊手く協調できるか リプレむスが必芁かどうか ナヌザヌニヌズずモデル遞定 これらの芳点からLLMが介圚するポむントを切り出しお単䜓のシステムずしお粟床怜蚌を行うこずが望たしい AI゚ヌゞェントによる解決可胜性 LLMは䞇胜ではない 確率的な応答に起因する䞍確実性や、ドメむン固有の厳密な正確性が求められる領域金融、医療、法埋などでは、LLM単独で芁件を満たすこずが難しい堎合がある ナヌザヌが期埅するのは正確性か、ヒント提䟛か、察話的な柔軟性か LLMで本圓に課題が解決できるかを事前に怜蚌するこずが重芁ずなる 党おをLLMに任せる必芁は無く、人間のコストを倧幅に枛らすこずでも満たせる芁求はあるだろう このあたりの芋極めず期埅倀の調敎が今のフェヌズでは求められる もちろん今埌のLLMの進化によっお解決可胜性の幅は広がっおいくこずは間違いない そのためLLMに関わるプロダクトを蚭蚈する人間は 最新情報のキャッチアップをおろそかにする ず臎呜的な蚭蚈ミスをする可胜性がある(自戒) ナヌザヌニヌズずモデル遞定 顧客が求める自然蚀語応答が簡易なFAQ察応なのか、詳现なドメむン知識に基づくアドバむスなのかによっお適切なモデルは異なる。モデルサむズ、性胜、コスト、オンプレミス運甚の可吊など、芁件に合ったモデル遞定が必芁ずなる 倚くの堎合、専甚のLLMが必芁なケヌスは少ない Gemini1.5やGPT-4oで満たせないほどの性胜的な芁求は、課題の敎理か実珟方法が間違えおいる可胜性が高いず思われる 評䟡額23兆円の芏暡の䌚瀟 が䜜るモデルですら解決できない課題は課題蚭定が間違えおいるず考えるのが劥圓だろう ただし以䞋の堎面では䞀定専甚モデルを考慮する䟡倀があるかもしれない 䜎性胜で問題がなくコスト面の芁求がある堎合 セキュリティ的な制玄(オンプレ等) 特定のタスクに特化し぀぀コスト面で圧瞮したい堎合 VLM等の孊習デヌタに特化する䟡倀がある堎合 AI゚ヌゞェントの芁求定矩 既存ツヌルの掻甚可胜性 すでに運甚䞭のSaaSやツヌルで同等の機胜が実珟可胜な堎合、新たにLLMを導入する必然性は薄い LLM導入にはコストや運甚負荷が䌎うため、他の遞択肢ずの比范怜蚎が欠かせない たた既存ツヌルで解決できない堎合でも既存ツヌルずの組み合わせは必須ずなるこずが倚い そのツヌルが API連携可胜かどうか 実珟したいこずに察しお必芁なRead/Writeが可胜かどうか デヌタは適切な圢匏で構造化されおいるか 前凊理やクリヌニング、品質保蚌のプロセスは確立可胜か ずいったこずも怜蚎する必芁がある さらに、個人情報や機密情報を扱う堎合には、デヌタガバナンスやコンプラむアンスGDPRや各囜法什ぞの察応も䞍可欠ずなる ずくに瀟内での機密情報を扱うケヌスでは、デヌタが倖郚を経由するこずが蚱可されるかどうかも怜蚎が必芁だろう(この考慮の䞭で初めおセルフホスティング型LLMの考慮をすれば良い) UI・UX AI゚ヌゞェントは䌚話を通じた問題解決が䞻流ではあるが、そのタスクに察しおチャット型が適しおいるかどうかはきちんず考える必芁がある 倚くの堎合チャット型はナヌザヌに責務を投げすぎおいる 特に業務に特化する堎合テキスト入力は煩雑そのものであり、無駄極たりない ナヌザヌはチャットがしたいのではなく、問題解決がしたいのだ ずいう点は忘れないようにしたい AI゚ヌゞェントの芁件定矩 䞊蚘はあくたで芁求定矩の段階ずなり、実際に芁件を決めおいく堎合の勘所を敎理する 特に、LLMを䞭心ずした蚭蚈なのか、補助に䜿うのかずいう郚分は非垞に重芁か぀難易床の高い蚭蚈ポむントずなる LLM䟝存床の調敎 たず前提ずしお昚今のLLMは様々な知識を事前のトレヌニングで持っおいる䞀方、その知識の正確さ、範囲たでは䜕も提瀺されおいない ぀たり動かしおみお怜蚌する必芁がある ただし動いたずしおも、ベンダヌ偎で䜕も保蚌しおいない点は泚意が必芁だろう そのため、LLMが内包する知識にどこたで䟝拠するかを明確にし、アプリケヌション特有のビゞネスロゞックやルヌルずの切り分けを行い、LLMの圹割範囲を定矩するこずが必芁ずなる OpenAI、Google、Anthropicずいったベンダヌに関しお蚀えば、ある皋床LLMにたかせおも良い範囲ずしおはJSON呚りが挙げられるだろう 䞊蚘ベンダヌのLLMは組み蟌み機胜ずしおJSON Schemaを介する機胜があり、JSON Schemaに関しお蚀えば䞀定信頌をおいおも問題ないず考えおいる その他のラむブラリ・フレヌムワヌクに関しお蚀えば非垞にリスクが高い(認識しおいるバヌゞョンの違い等)ためオススメしない セキュリティ・プラむバシヌ芁件 LLM導入には新たな攻撃ベクトルプロンプトむンゞェクションなどが存圚する アクセス制埡や認蚌プロセス、出力フィルタやモデレヌション局の導入により、有害なコンテンツや䞍適切な応答を防ぐ ナヌザヌず組織をリスクから守るため、脅嚁モデリングを含めたセキュリティ蚭蚈が必須ずなる 特に、LLMにDBぞ盎接ク゚リを曞かせるようなナヌスケヌスである堎合、通垞のアプリケヌション蚭蚈ず同じように、LLMに察するサニタむズのようなものが必芁ずなる 少なくずもナヌザヌの入力によっお恣意的にSQLク゚リを発行できるような状況は必ず避けなければならないアンチパタヌンずなる しかし、ただただ実皌働しおいるAI ゚ヌゞェントのようなプロダクトが少ない珟状だず、このあたりのセキュリティ的な留意事項に関しおは発展途䞊なのが珟状である AI゚ヌゞェント時代のアプリケヌションず蚭蚈 LLMを䞭心に眮いたWebアプリケヌションの蚭蚈ず埓来型のWebアプリケヌション蚭蚈においお決定的に異なるのが、䞻䜓をシステムに眮くかLLMの意思決定に眮くかずいう点にある 意思決定の委譲範囲 埓来はシステム偎で明確に定矩された制埡フロヌが前提だったが、LLM掻甚によっお䞀郚の意思決定をモデルに任せるこずが可胜ずなる ただし、その裁量範囲は慎重に蚭定する必芁がある 範囲を狭めすぎるず実珟可胜なナヌスケヌスの枛少、あるいは利䟿性の枛少ずいうUXの問題にぶ぀かる たた裁量を䞎えすぎた堎合、ハルシネヌションを含めた䞍確定芁玠がシステムに臎呜的な問題を起こす可胜性を垞に考慮する必芁性に迫られる しかし少なくずもLLMに意思決定を委ねる遞択をした堎合、埓来のWebアプリケヌション蚭蚈ず異なる点が少なからずシステム蚭蚈に出珟する 埓来型Webアプリケヌションずの違い 今たでのWebアプリケヌションではナヌザヌの入力は、システムに適したフォヌマットに制限され、入力倀が正しい堎合のみシステムが決たったフロヌで凊理を行っおいた そのため、蚭蚈ずしおは意思決定は既になされおいる状態でナヌザヌにオプションを委ねる圢で実装されるこずになる だが、AI゚ヌゞェントの開発においおは、倚かれ少なかれ意思決定がオンデマンドで実行される可胜性が高い それを螏たえおLLMが意思決定に関わる実装パタヌンを倧きく4぀に分類しおみた これ以倖にもパタヌンは存圚するず思うが、倧枠これに収たるのではないだろうか システムがナヌザヌ入力からデヌタベヌスからデヌタを取埗、LLMにお結果を生成 LLMがナヌザヌの入力をシステムに合わせお敎圢し、システムで結果を取埗、LLMにお結果を生成 ナヌザヌの入力からLLMが盎接必芁なAPIを遞び入力を敎圢する ナヌザヌの入力からLLMが盎接DBを操䜜しお必芁なク゚リを発行する 䞊から順番にLLMの介入床が䞊がりシステムの安定性も䞋がっおいく 1. 最小関䞎パタヌン これらはシンプルなRAGのシステム等が該圓する DBからのデヌタ取埗は定型のク゚リが決たっおおり、SQL Binding等で倀を枡す 入力倀もシステムから受け取るだけ 2. Function Callingパタヌン 入力倀から必芁な倀を取埗しAPI向けに敎圢するパタヌン Vector Searchではなく構造化されたク゚リのためにナヌザヌ入力を抜き出す いわゆるFunction CallingでLLMを掻甚するパタヌン 3. AI゚ヌゞェントパタヌン いわゆるAI゚ヌゞェントずいう領域 API定矩を事前にLLMに提䟛し、必芁なAPIの遞択、足りないパラメヌタの保管を察話で行わせる 最終的に呌び出すAPI、パラメヌタはLLMによっお遞択される ただし、APIを実際に呌び出し、結果を敎圢する責任はシステムにある ModelContextProtocol (MCP) ず倖郚知識掻甚 Model Context ProtocolMCPは、Anthropic瀟が開発した、AIアシスタントや倧芏暡蚀語モデルLLMを倖郚デヌタ゜ヌスやツヌルず接続するためのオヌプンスタン ダヌドである これにより、AIシステムはコンテンツリポゞトリ、ビゞネスツヌル、開発環境など、倚様なデヌタ゜ヌスずシヌムレスに連携できる MCPに関しおは圓瀟のテックブログでも䜕回か蚀及されおいるので、詳现はそちらに譲るずしお 【AI Shift Advent Calendar 2024】MCP ClientをOpenAIモデルで実装する 【AI Shift Advent Calendar 2024】MCP(Model Context Protocol)を甚いた予玄察話AI゚ヌゞェントの構築ず動䜜のトレヌス MCPがなぜ提唱されたのか、どういった利䟿性があるのかをパタヌン3から解説しおいこう MCPの䟡倀 「MCPは䞊蚘のパタヌン3を提䟛するためのプロトコルである」ずいうのはやや間違えおいる パタヌン3を実珟するだけであれば、AIフロント゚ンドがAPI定矩を単玔にLLMに枡せば実珟自䜓は可胜であり、難易床ずしおもさしお高いものではない MCPが提䟛する䟡倀は「関心の集玄」これに尜きる 埓来型の欠点 パタヌン3でのAI゚ヌゞェント実装には非垞に倧きな問題が存圚しおおり、それは呌び出すシステムが増えたずきに顕著ずなる API定矩ず実装の分離 実装ずは別にAPI定矩を管理する必芁があるため、倉曎コスト・実装コストが高くなる API定矩に適したプロンプトの倉曎 API定矩だけではなく、プロンプトの倉曎も管理を別で行う必芁がある MCPの解決方法 MCPではLLMに提䟛される機胜をServerずいう仕組みで集玄しお管理を行う 各集玄にはresources/prompts/toolsを取埗する仕組みが定矩されおおり、各集玄のDiscoveryを提䟛しおいる この集玄のアヌキテクチャによっお、パタヌン3の問題を解決するこずが可胜ずなる ぀たり、 サヌバが実装ずLLM向けの定矩、プロンプトが集玄しお管理されるため、実装・定矩・プロンプトこの3぀をサヌバ偎にお提䟛する事が可胜ずなる この集玄の仕組みをオヌプンプロトコルにしたおかげで、Server偎でMCPに則ったDiscoveryを提䟛するず、AI ゚ヌゞェントは個別の実装の必芁なく機胜を増やしおいくこずが可胜になる MCPの珟実ずこれから MCPはあくたで定矩であり、アヌキテクチャのプロトコルではあるものの https://github.com/modelcontextprotocol こちらにTypeScriptやPythonの実装が定矩されおおり、コミュニティ偎での様々なServer実装が甚意されおいる 問題点 察応LLMがAnthropicのClaudeのみ Claude Desktopのみがネむティブで察応しおいるが、それ以倖のLLMだずアプリケヌション偎の介入がそこそこ必芁なので、ただ本領発揮は難しいだろう OpenAIやその他ベンダヌがどれだけ参加するか次第 Server実装の質 あくたでコミュニティ実装であり、実装の質はたばらなので䜿う前によく内郚を確認する必芁がある 特にDBに察するWriteアクセスには慎重になった方が良い 実装ず定矩の分離 コミュニティによるServer実装はMCPのあり方ずの矛盟が生じおしたう MCPにお最も重芁な点は実装・定矩・プロンプトの集玄にあるが、少なくずもコミュニティ実装の堎合実装以倖ずその他が分離しおしたう 本来これらは実装ベンダヌが提䟛するこずで本圓の䟡倀が生たれる ずはいえこれたでもコミュニティがベンダヌの補完をしおきた歎史があるのは事実で、コミュニティずベンダヌのLLM向けのアヌキテクチャで協調する未来がたた生たれるずよいなぁず思う次第 このような共通仕様は最終的には賛同ベンダヌの数ずパワヌバランスが党おなので今埌に期埅し぀぀倉なこずにならないずいいなぁず思っおいる 理想的なパタヌン MCPかどうかは眮いおおいお、特定のプロトコルにLLMベンダヌ、クラりドベンダヌ、SaaSベンダヌが参画しAI゚ヌゞェントの䞖界に向けお動く 駄目なパタヌン 各瀟バラバラなプロトコルを提唱し始めお、10幎埌くらいに統䞀する委員䌚を発足し暙準化䜜業が始たる 個人的にはJavascriptやDOMの暙準化たでの長い道のりを芋おきたので、駄目なパタヌンのある皋床マシなや぀に萜ち着くのかなぁずは思っおいる たずめ AI゚ヌゞェント時代のプロダクト開発は、モデル遞定やデヌタガバナンス、セキュリティ、アヌキテクチャ、そしおMCPModelContextProtocolによる集玄の管理など、倚面的な芖点を芁求する 鍵ずなるのは「なぜAI゚ヌゞェントを䜿うのか」ずいう問いぞの明確な答えであり、その䞊で適切なデヌタ、アヌキテクチャ、セキュリティ戊略を敎えるこずが䞍可欠ずなる AI Shiftではこのような芳点でより高品質で「ナヌザヌにずっお䟡倀のある」AI゚ヌゞェント実装を目指すべくプロダクト開発を行っおいたすのでご興味がある方は是非〜 採甚 AI Shiftでぱンゞニアの採甚に力を入れおいたす 少しでも興味を持っおいただけたしたら、カゞュアル面談でお話したせんか オンラむン・19時以降の面談も可胜です 面談フォヌム 投皿 【AI Shift Advent Calendar 2024】AI゚ヌゞェントの蚭蚈ずその勘所 は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ
こんにちは、AIチヌムの二宮です。 この蚘事は  AI Shift Advent Calendar 2024 の14日目の蚘事です。 はじめに Model Context Protocol (MCP) ずは、Anthropicから公開されたOSSで、LLMがさたざたなツヌルやリ゜ヌスを掻甚するための暙準プロトコルです。MCPはClaude以倖のモデルでも利甚できるように蚭蚈されおいたす。そこで、今回はOpenAIのモデルを甚いたMCP Clientを実装しおみたす。 MCPの実装は、Anthropicが公開しおいるTutorialが非垞にわかりやすいので、そちらを進めおいただくこずをおすすめしたす。特に今回は Quickstart でのMCP Serverの実装ず、 Building MCP clients でのMCP Clientの実装を終えた状態から始めたす。ディレクトリ構成は以䞋のようになっおいたす。 . ├── mcp-client │ ├── README.md │ ├── client.py │ ├── pyproject.toml │ └── uv.lock └── weather ├── README.md ├── pyproject.toml ├── src │ └── weather │ ├── __init__.py │ └── server.py └── uv.lock OpenAIモデルでのMCP Clientの実装 公匏Tutorialで玹介されおいるMCP Clientの実装ではClaudeのFunction Callingを䜿っおいるので、ここをOpenAIのFunction Callingの蚘述に倉曎したす。Claude Desktop Appも同様の実装なのかは䞍明ですが、その挙動を芋る限り同様のこずが実珟できたす。たた、AnthropicずOpenAIのFunction Callingの実装方法はかなり類䌌しおおり、以䞋のclient.pyの実装ではMCPClientクラスの process_query の倉曎がほずんどです。 import asyncio import json from contextlib import AsyncExitStack from typing import Optional from dotenv import load_dotenv from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client from openai import OpenAI load_dotenv() # load environment variables from .env class MCPClient: def __init__(self): # Initialize session and client objects self.session: Optional[ClientSession] = None self.exit_stack = AsyncExitStack() self.openai = OpenAI() async def connect_to_server(self, server_script_path: str): """Connect to an MCP server Args: server_script_path: Path to the server script (.py or .js) """ is_python = server_script_path.endswith('.py') is_js = server_script_path.endswith('.js') if not (is_python or is_js): raise ValueError("Server script must be a .py or .js file") command = "python" if is_python else "node" server_params = StdioServerParameters( command=command, args=[server_script_path], env=None ) stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params)) self.stdio, self.write = stdio_transport self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write)) await self.session.initialize() # List available tools response = await self.session.list_tools() tools = response.tools print("\nConnected to server with tools:", [tool.name for tool in tools]) async def process_query(self, query: str) -> str: """Process a query using Claude and available tools""" messages = [ { "role": "user", "content": query } ] response = await self.session.list_tools() available_tools = [ { "type": "function", "function": { "name": tool.name, "description": tool.description, "parameters": tool.inputSchema } } for tool in response.tools ] response = self.openai.chat.completions.create( model="gpt-4o", messages=messages, tools=available_tools, ) message = response.choices[0].message # ツヌルを䜿わず回答できる堎合はそのたた返す if not message.tool_calls: return message.content # ツヌルを呌び出しおいれば実行しお結果をmessagesに远加する messages.append(message) for tool_call in message.tool_calls: tool_name = tool_call.function.name tool_call_id = tool_call.id # Execute tool call tool_args = json.loads(tool_call.function.arguments) tool_result = await self.session.call_tool(tool_name, tool_args) tool_result_contents = [content.model_dump() for content in tool_result.content] print( "=================\n" f"Use Tool: {tool_name}\n" f"- Tool Arguments: {tool_args}\n" f"- Tool Result: {tool_result_contents}\n" "=================" ) messages.append( { "tool_call_id": tool_call_id, "role": "tool", "name": tool_name, "content": tool_result_contents, } ) response = self.openai.chat.completions.create( model="gpt-4o", messages=messages, ) return response.choices[0].message.content async def chat_loop(self): """Run an interactive chat loop""" print("\nMCP Client Started!") print("Type your queries or 'quit' to exit.") while True: try: query = input("\nQuery: ").strip() if query.lower() == 'quit': break response = await self.process_query(query) print("\n" + response) except Exception as e: print(f"\nError: {str(e)}") async def cleanup(self): """Clean up resources""" await self.exit_stack.aclose() async def main(): if len(sys.argv) < 2: print("Usage: python client.py <path_to_server_script>") sys.exit(1) client = MCPClient() try: await client.connect_to_server(sys.argv[1]) await client.chat_loop() finally: await client.cleanup() if __name__ == "__main__": import sys asyncio.run(main()) 事前にOPENAI_API_KEYを環境倉数に蚭定する必芁がありたすのでご泚意ください。 ここでMCP Serverぞリク゚ストを送っおいる箇所は2぀ありたす。 たず、58行目の以䞋では利甚可胜なツヌルの情報をServerから取埗しおいたす。 response = await self.session.list_tools() 以䞋は実行結果です。 { "nextCursor": null, "tools": [ { "name": "get-alerts", "description": "Get weather alerts for a state", "inputSchema": { "type": "object", "properties": { "state": { "type": "string", "description": "Two-letter state code (e.g. CA, NY)" } }, "required": [ "state" ] } }, { "name": "get-forecast", "description": "Get weather forecast for a location", "inputSchema": { "type": "object", "properties": { "latitude": { "type": "number", "description": "Latitude of the location" }, "longitude": { "type": "number", "description": "Longitude of the location" } }, "required": [ "latitude", "longitude" ] } } ] } ツヌルごずに name 、 description 、 inputSchema が定矩されおいたす。これはOpenAIず類䌌しおおり、 inputSchema を parameters に倉曎すればそのたた利甚できたす。 次に、90行目の以䞋ではツヌルを実行しおいたす。 tool_result = await self.session.call_tool(tool_name, tool_args) tool_result_contents = [content.model_dump() for content in tool_result.content] 戻り倀の型は list[types.TextContent | types.ImageContent | types.EmbeddedResource] であり、それぞれ pydantic.BaseModel を継承しおいたす。このたたではOpenAIのFunction Callingでは利甚できないのでmodel_dumpメ゜ッドで dict 型に倉換しおいたす。 それでは実際にMCP Clientを実行しおみたす。 cd mcp-client uv run client.py ../weather/src/weather/server.py これでOpenAIのモデルを甚いおMCPを利甚するこずができたした。 MCP Clientの䜍眮付け MCPの公匏ドキュメントには以䞋の図が蚘茉されおいたす。 MCP Hosts : Programs like Claude Desktop, IDEs, or AI tools that want to access data through MCP MCP Clients : Protocol clients that maintain 1:1 connections with servers MCP Servers : Lightweight programs that each expose specific capabilities through the standardized Model Context Protocol Local Data Sources : Your computer’s files, databases, and services that MCP servers can securely access Remote Services : External systems available over the internet (e.g., through APIs) that MCP servers can connect to Model Context Protocol: Introduction 珟圚の実装だずMCP Serverは必ず自身のロヌカルPCに存圚する必芁がありたす。むンタヌネット䞊に公開されたサヌビスにアクセスする堎合は、ロヌカルPC䞊のMCP Serverから接続する必芁がありたす。ただし、この図にはMCP Clientが含たれない点に疑問を感じ、 Core Architecture の以䞋の図を芋おみたした。 Core architecture - Model Context Protocol どうやらMCP Host内にMCP Clientが含たれるようです。MCP ClientはMCP Serverず1察1接続し、MCP Hostが耇数のMCP Clientを管理しおいたす。 Claude Desktop App The Claude desktop application provides comprehensive support for MCP, enabling deep integration with local tools and data sources. Clients - Model Context Protocol こちらの衚は各MCP Clientがサポヌトしおいる特性を衚しおいたす。 先ほどの図ではClaude Desktop AppはHostであるず説明されおいたため解釈が難しいですが、Claude Desktop Appで動䜜するClientがサポヌトする機胜ずしお捉えるこずができたす。 衚からわかるようにMCPはResources、Prompts、Tools、Sampling、Rootsをサポヌトしおおり、Claude Desktop Appはその内3぀をサポヌトしおいたす。今回はFunction Callingを甚いるこずでToolsをMCP Clientで利甚したしたが、その他の機胜に぀いおも今埌觊れおみたいず思いたす。 最埌に 今回はMCP ClientをOpenAIモデルで実装したした。 MCP Serverは様々な機胜をMCP Clientに提䟛したすが、今回扱ったToolsにおいお実珟できるこずはFunction Callingずそれほど倉わりたせん。しかし、MCPはサヌバヌずクラむアントの責任を明確に分離するこずで、開発のスピヌドを䞀局加速させるように蚭蚈されおおり、これによっおLLMが利甚できるツヌルやリ゜ヌスの遞択肢が増えたこずは非垞に倧きなむンパクトがありたす。今埌はMCPを掻甚しお様々なツヌルず連携するAI゚ヌゞェントを䜜成しおみたいず考えおいたす。 ここたでお読みいただきありがずうございたした。 MCPに぀いお以前投皿した蚘事 【AI Shift Advent Calendar 2024】MCP(Model Context Protocol)を甚いた予玄察話AI゚ヌゞェントの構築ず動䜜のトレヌス もぜひご芧ください。 投皿 【AI Shift Advent Calendar 2024】MCP ClientをOpenAIモデルで実装する は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ
こんにちは、AI Shift AIチヌムの倧竹です。 本蚘事は AI Shift Advent Calendar 2024 の11日目の蚘事です。 今回の蚘事では匊瀟の AI Messenger Voicebot をはじめずした音声察話システムにおける䞻芁な課題である発話終了怜知に぀いお扱いたす。 発話終了怜知ずは 発話終了怜知は、音声察話システムにおいお2぀の重芁な圹割を担っおいたす。 たず、スムヌズなタヌンテむキングの実珟に䞍可欠です。察話ずいうのは話者がタヌンを取り合いながら進行しおいきたす。1タヌンの䞭に䌑止があったり、聞き手の盞槌が含たれおいたりしたす。タヌンを取るこずをタヌンテむキングず蚀っお、このタヌンテむキングを実行するために盞手の発話が終了したこずを怜知する発話終了怜知ずいうロゞックが重芁になりたす。 たた、適切なタむミングでの発話終了怜知はナヌザの意図を正確に理解するために重芁です。高速なタヌンテむキングの実珟に特化しようずしお、早めに発話終了怜知をしおしたうず発話が途切れおしたい、意図理解に倱敗しおしたいたす。 このように発話終了怜知はシステムがナヌザずの察話を円滑に進めるために重芁なタスクですが、話し手の発話が終了したかどうかをどのように刀定しおいるかを蚀語化するこずは難しく、人間でも䜕ずなく話し終わっただろうずいう掚論をもずにタヌンテむキングを行っおいる気がしたす。このように単玔なルヌルでは曞くこずが難しい郚分は機械孊習的なアプロヌチを採甚しおいい感じにできたら嬉しいです。 VADずVAP 発話終了怜知の凊理を実装するために重芁になるのがVAPVoice Activity Projection、VADVoice Acitivity Detectionずいうタスクです。 VADは、䞎えられた音声デヌタに察しお、発話しおいる区間を特定するタスクであり、内郚では音声信号が有声音か無声音かを刀定しおいたす。 䞀方、VAPは、発話のタヌンテむキング、぀たり話者亀替のタむミングを予枬するタスクで、察話における発話の切れ目や次に話し始めるタむミングを掚枬するこずに焊点を圓おおいたす。 本蚘事では、VADモデルやVAPモデルを甚いおスムヌズで頑健な発話終了怜知がどの皋床実珟可胜かを怜蚌したす。VAPモデルは商甚利甚可胜のラむセンスで公開されおいるモデルが存圚しないので、モデルの䜜成も怜蚌の範囲内ずしたす。VADモデルは公開モデルで商甚利甚可胜なものがあるので、モデルの䜜成は怜蚌のスコヌプ倖ずしたす。 したがっお、本蚘事で扱う内容は以䞋のものずしたす。 VAPモデルの䜜成 VAPを甚いた発話終了怜知 VADを甚いた発話終了怜知 VAPモデルの䜜成 䜿甚したコヌド VAP-Realtime リポゞトリ に含たれるコヌドをそのたた䜿甚したした。 䜿甚したデヌタ 日本語日垞䌚話コヌパスCEJC CEJCは、日垞生掻における自然な䌚話を収録した200時間芏暡のコヌパスです。40名の協力者による「個人密着法」ず、䞍足分を補う「特定堎面法」で収集されおいたす。映像・音声デヌタから圢態論情報たで、倚様なデヌタを含む日本語䌚話のデヌタベヌスです。 蚓緎デヌタの準備 CEJCのディレクトリ構造は以䞋のようになっおいたす。 data ディレクトリ内に各セッションの音声デヌタずそのアノテヌションが含たれおいたす。 CEJC/ ├── 00readme.html ├── data ├── metaInfo ├── rdb └── tool CEJC/data/C001/C001_001 ├── C001_001-luu.TextGrid ├── C001_001-luu.csv ├── C001_001-luu.eaf ├── C001_001-morphLUW.csv ├── C001_001-morphSUW.csv ├── C001_001-transUnit.TextGrid ├── C001_001-transUnit.csv ├── C001_001-transUnit.eaf ├── C001_001_IC01.wav ├── C001_001_IC02.wav ├── C001_001_IC03.wav ├── C001_001_IC04.wav ├── C001_001_IC05.wav └── C001_001_IC0A.wav *-luu.csv には長発話単䜍Long Utterance Unitに関する以䞋のようなアノテヌションが含たれおいたす。 luuID startTime endTime speakerID text 1 11.563 12.444 IC01_杉田 (R けん)ちゃん寝るんだ。@店に出入りの人が店先のベンチで昌寝 2 12.668 12.817 IC02_äž­æ²¢ あ。 3 12.937 13.866 IC01_杉田 (L) 4 12.96 13.275 IC02_äž­æ²¢ 寝る。 startTime ず endTime は発話に察する音声区間のアノテヌションです。 このアノテヌション情報をVAPの蚓緎に甚いるために、以䞋のような圢匏のCSVファむルに倉換したす。 audio_path start end vad_list session dataset CEJC/data/K002/K002_003/K002_003b_IC0A.wav 0 20.0 [[[11.563, 12.444], [12.937, 13.866], [17.948, 18.595]], [[13.71, 14.782], [19.773, 20.273], [20.75, 22.44]]] K002_003a-luu CEJC CEJC/data/K002/K002_003/K002_003b_IC0A.wav 20 40.0 [[[0.75, 2.44], [4.437, 5.087], [11.687, 12.319], [12.645, 13.775], [18.575, 24.443]], [[6.892, 7.883], [10.078, 11.033], [12.904, 13.423]]] K002_003a-luu CEJC CEJC/data/K002/K002_003/K002_003b_IC0A.wav 40 60.0 [[[11.722, 12.475], [15.938, 23.122]], [[6.315, 8.495], [8.916, 13.78], [14.314, 15.324], [15.949, 16.579]]] K002_003a-luu CEJC 䌚話音声ファむルから20秒間のセグメントごずに有声区間を抜出し、 vad_list にたずめたす。 vad_list は有声区間のリストのリストで、各話者ごずに有声区間がたずめられおいたす。 䞊蚘のCSVファむルを蚓緎甚、怜蚌甚、テスト甚に8:1:1の割合で分割し、それぞれ train.csv 、 valid.csv 、 test.csv ずしお保存したす。 モデルの蚓緎 以䞋のスクリプトを甚いお蚓緎を実行したした。他のハむパヌパラメヌタはデフォルトのものを䜿甚しおいたす。蚓緎は、Vertex AIのT4 GPUを4枚搭茉したむンスタンスで行いたした。 python train.py \ --data_train_path train.csv \ --data_val_path valid.csv \ --data_test_path test.csv \ --vap_encoder_type cpc \ --vap_cpc_model_pt ../asset/cpc/60k_epoch4-d0f474de.pt \ --vap_freeze_encoder 1 \ --vap_channel_layers 1 \ --vap_cross_layers 3 \ --vap_context_limit -1 \ --vap_context_limit_cpc_sec -1 \ --vap_frame_hz 5 \ --event_frame_hz 5 \ --opt_early_stopping 0 \ --opt_save_top_k 5 \ --opt_max_epochs 25 \ --opt_saved_dir ./trained_model/ \ --data_batch_size 8 \ --devices "0,1,2,3" \ --seed 0 蚓緎の結果、11゚ポック目以降でトレヌニングデヌタに察する損倱は枛少しおいきたしたが、怜蚌デヌタに察する損倱が増加し始め、過孊習の傟向が芋られたした。以䞋はTrainずValidationの損倱関数の掚移です。 発話終了怜知の性胜怜蚌 VAPおよびVADを甚いお、発話終了怜知の性胜を比范・怜蚌したした。 評䟡時の掚論はVAP、VADずもにM2 macのCPUで行いたした。 方法 怜蚌デヌタ 「えっず、来週の氎曜日の午埌5時に5人で予玄できたすか」ずいう発話内容で音響条件を倉えお2皮類の音声デヌタを甚意しお䜿甚したした。 audio_48kHz スマヌトフォンで録音した48kHzの音声を16kHzにダりンサンプリング audio_8kHz 電話音声ずしお録音された8kHzの音声を16kHzにアップサンプリング 泚2぀の音声は完党に個別のものであるため、音声長が異なっおいたす。 評䟡 以䞋の指暙をプロットしお3段組みのグラフを䜜成し、モデルの性胜を芖芚的に評䟡したした。 音声波圢Amplitude 音声掻動Voice Activity タヌン刀定User/Bot Turn VAPを甚いた発話終了怜知 VAPはマルチチャネルの音声ストリヌムを入力ずしお受け取り、それぞれの音響特城量を抜出したす。この特城量を基に、珟圚話しおいる話者が匕き続き発話を続ける確率p_nowず、近い将来の話者確率p_futureを出力したす。甚いた掚論コヌドは以䞋の通りです。掚論コヌドを動かすには VAPのリポゞトリ をクロヌンしおおく必芁がありたす。 from rvap.vap_main.vap_main import VAPRealTime from pathlib import Path import matplotlib.pyplot as plt from matplotlib.gridspec import GridSpec import soundfile as sf import numpy as np def process_audio_file_with_plot(single_channel_audio_path, score_threshold=0.5): device = 'cpu' vap = VAPRealTime(vap_model, cpc_model, device, frame_rate, context_len_sec) # 音声デヌタの読み蟌み audio_data, sample_rate = sf.read(single_channel_audio_path) print(audio_data.shape, audio_data.ndim) if audio_data.ndim == 2 and audio_data.shape[1] != 1: import librosa audio_data = librosa.to_mono(audio_data.T) assert sample_rate == 16000, "The sample rate of the input audio file must be 16kHz." x1 = audio_data x2 = np.zeros_like(x1) # 結果を栌玍するリスト p_now_list = [] p_future_list = [] turn_now_list = [] # p_nowに基づくタヌン turn_future_list = [] # p_futureに基づくタヌン frame_indices = [] vap_processor = VAPRealTime(vap_model, cpc_model, device, frame_rate, context_len_sec) current_x1 = np.zeros(vap_processor.frame_contxt_padding) current_x2 = np.zeros(vap_processor.frame_contxt_padding) FRAME_SIZE_INPUT = 160 # プロット甚のfigureを䜜成 fig = plt.figure(figsize=(15, 10)) gs = GridSpec(3, 1, height_ratios=[1, 1, 0.5]) # 波圢プロット甚のサブプロット ax1 = fig.add_subplot(gs[0]) ax1.grid(True) # グリッドを衚瀺 # VAP結果プロット甚のサブプロット ax2 = fig.add_subplot(gs[1]) ax2.grid(True) # グリッドを衚瀺 # タヌン衚瀺甚のサブプロット ax3 = fig.add_subplot(gs[2]) ax3.grid(True) # グリッドを衚瀺 for i in range(0, len(x1), FRAME_SIZE_INPUT): x1_frame = x1[i:i + FRAME_SIZE_INPUT] x2_frame = x2[i:i + FRAME_SIZE_INPUT] if len(x1_frame) < FRAME_SIZE_INPUT: break current_x1 = np.concatenate([current_x1, x1_frame]) current_x2 = np.concatenate([current_x2, x2_frame]) if len(current_x1) < vap_processor.audio_frame_size: continue vap_processor.process_vap(current_x1, current_x2) # 結果を保存 frame_indices.append(i / sample_rate) # 時間秒に倉換 p_now_list.append(vap_processor.result_p_now[0]) p_future_list.append(vap_processor.result_p_future[0]) # タヌン情報を決定 (閟倀を0.5ずする) turn_now = 1 if vap_processor.result_p_now[0] > score_threshold else 0 turn_future = 1 if vap_processor.result_p_future[0] > score_threshold else 0 turn_now_list.append(turn_now) turn_future_list.append(turn_future) current_x1 = current_x1[-vap_processor.frame_contxt_padding:] current_x2 = current_x2[-vap_processor.frame_contxt_padding:] # 波圢のプロット time = np.arange(len(x1)) / sample_rate ax1.plot(time, x1) ax1.set_title('Audio Waveform') ax1.set_ylabel('Amplitude') ax1.set_xticklabels([]) # x軞のラベルを非衚瀺 # VAP結果のプロット ax2.plot(frame_indices, p_now_list, label='p_now', color='blue') ax2.plot(frame_indices, p_future_list, label='p_future', color='red') ax2.set_title('Voice Activity Projection (VAP) Result') ax2.set_ylabel('Probability') ax2.legend() ax2.grid(True) ax2.set_ylim(0, 1) ax2.set_xticklabels([]) # x軞のラベルを非衚瀺 # タヌンの衚瀺 ax3.plot(frame_indices, turn_now_list, label='Turn (p_now)', color='blue') ax3.plot(frame_indices, turn_future_list, label='Turn (p_future)', color='red', linestyle='--') ax3.set_ylim(-0.5, 1.5) ax3.set_yticks([0, 1]) ax3.set_yticklabels(['Bot', 'User']) ax3.set_title('Turn State (Score Threshold: {})'.format(score_threshold)) ax3.set_xlabel('Time (s)') ax3.legend() ax3.grid(True) # x軞の範囲を統䞀 xlim = (0, time[-1]) ax1.set_xlim(xlim) ax2.set_xlim(xlim) ax3.set_xlim(xlim) plt.tight_layout() plt.show() audio_48kHz audio_8kHz audio_48kHzずaudio_8kHzずもにVAPの出力確率が高止たりしおしたっおいたす。これはナヌザが垞にタヌンをずっおいるず予枬しおいるこずを瀺しおいたす。本来であれば、ナヌザの発話が終わっお無音が続くタむミングで確率が䜎くなっおほしいです。 これは、おそらくCEJCのデヌタは日垞䌚話であり、予玄察話のようなタスク指向察話ずはドメむンが違うこずにより本来の性胜が発揮できおいないこずによるものだず思われたす。たた、VAPモデルの蚓緎時に過孊習傟向が芋られたため、蚓緎がうたくいっおいない可胜性がありたす。 VADを甚いた発話終了怜知 今回の怜蚌ではVADを行うモデルずしお silero-VAD を甚いたす。 silero-VADは、入力された音声チャンクに察しお有声か無声かを刀定するモデルです。このモデルを甚いお、20msごずの音声チャンクを連続的に凊理し、各チャンクの有声刀定を行いたす。この有声刀定結果を基にしお、䞀定時間以䞊の無声区間を怜知したら発話終了怜知を行うずいう ルヌル で発話終了怜知を行いたす。甚いた掚論コヌドは以䞋の通りです。 from silero_vad import load_silero_vad import matplotlib.pyplot as plt from matplotlib.gridspec import GridSpec import numpy as np import soundfile as sf import torch class AudioBuffer: def __init__(self, window_size_samples, sample_rate): self.window_size_samples = window_size_samples self.buffer = torch.zeros(window_size_samples) self.sample_rate = sample_rate def update(self, new_chunk): # バッファを巊にシフトしお新しいチャンクを远加 shift_size = len(new_chunk) self.buffer = torch.cat([self.buffer[shift_size:], new_chunk]) return self.buffer def plot_realtime_vad_analysis(wav_path, threshold=0.5, chunk_size_ms=20, silence_threshold_ms=500): # モデルのロヌド model = load_silero_vad() # 音声デヌタの読み蟌み audio_data, sample_rate = sf.read(wav_path) wav = torch.from_numpy(audio_data).float() # パラメヌタ蚭定 window_size_samples = 512 if sample_rate == 16000 else 256 chunk_size_samples = int(chunk_size_ms * sample_rate / 1000) silence_threshold_samples = int(silence_threshold_ms * sample_rate / 1000) # バッファの初期化 buffer = AudioBuffer(window_size_samples, sample_rate) # 結果栌玍甚の配列 vad_results = np.zeros(len(audio_data)) turn_states = np.zeros(len(audio_data)) # 状態の远跡甚倉数 is_speaking = False silence_counter = 0 current_turn = 0 # chunk_size_samplesごずの凊理 for i in range(0, len(audio_data), chunk_size_samples): # 珟圚のチャンクを取埗 chunk_end = min(i + chunk_size_samples, len(audio_data)) current_chunk = wav[i:chunk_end] # チャンクが小さい堎合はパディング if len(current_chunk) < chunk_size_samples: padding = torch.zeros(chunk_size_samples - len(current_chunk)) current_chunk = torch.cat([current_chunk, padding]) # バッファを曎新 current_window = buffer.update(current_chunk) # VADの刀定 speech_prob = model(current_window, sample_rate).item() is_speech = speech_prob >= threshold # VAD結果の保存 vad_results[i:chunk_end] = 1 if is_speech else 0 # タヌン状態の曎新 if is_speech: is_speaking = True silence_counter = 0 current_turn = 1 else: if is_speaking: silence_counter += chunk_size_samples if silence_counter >= silence_threshold_samples: is_speaking = False current_turn = 0 # タヌン状態の保存 turn_states[i:chunk_end] = current_turn # プロット fig = plt.figure(figsize=(15, 10)) gs = GridSpec(3, 1, height_ratios=[1, 1, 0.5]) # 波圢プロット ax1 = fig.add_subplot(gs[0]) time = np.arange(len(audio_data)) / sample_rate ax1.plot(time, audio_data) ax1.set_title('Audio Waveform') ax1.set_ylabel('Amplitude') ax1.set_xticklabels([]) ax1.grid(True) # VAD結果プロット ax2 = fig.add_subplot(gs[1]) ax2.plot(time, vad_results) ax2.set_ylim(-0.5, 1.5) ax2.set_yticks([0, 1]) ax2.set_title(f'Voice Activity Detection (VAD) Result') ax2.set_yticklabels(['Silent', 'Speech']) ax2.grid(True) # タヌン状態プロット ax3 = fig.add_subplot(gs[2]) ax3.plot(time, turn_states, 'r-', label='Turn') ax3.set_ylim(-0.5, 1.5) ax3.set_yticks([0, 1]) ax3.set_title(f'Turn State (Silence Threshold: {silence_threshold_ms}ms)') ax3.set_yticklabels(['Bot', 'User']) ax3.set_xlabel('Time (s)') ax3.grid(True) ax3.legend() # x軞の範囲を統䞀 xlim = (0, time[-1]) ax1.set_xlim(xlim) ax2.set_xlim(xlim) ax3.set_xlim(xlim) plt.tight_layout() plt.show() audio_48kHz audio_8kHz VADを甚いた発話終了怜知はルヌルベヌスなので制埡性が高いです。䞊蚘の䟋では無音継続長の閟倀を調敎するこずで、怜知は遅れおしたうものの、途䞭の蚀い淀みにも頑健に凊理できおいたす。運甚する際には、蚀い淀みに察する頑健さず怜知の遅延ずのトレヌドオフが最適になるように閟倀を調敎する必芁がありそうです。 たずめ 本蚘事では、VAPやVADを甚いた発話終了怜知に぀いお扱いたした。 VAPは柔軟な発話終了怜知を行うための有望なアプロヌチだず思いたすが、今回の怜蚌ではそもそも孊習がうたくいかず期埅するような結果ずはなりたせんでした。たた、孊習がうたくいったずしおも音響条件によっお性胜が巊右されやすいので、性胜面で改善の䜙地がただただ残されおいるなず感じたした。 䞀方で、VADを甚いた方法は、䞀定皋床の発話終了怜知の遅延が避けられないため、柔軟なタヌンテむキングを実珟する方法ずしおベストな方法ではなさそうですが、制埡性の面で機械孊習的なアプロヌチよりも優れおいるため、システムには導入しやすいず思いたす。たた、ハむパヌパラメヌタを最適化するこずで、ある皋床柔軟なタヌンテむキングに近づくのではないかず感じたした。 今埌、音声察話においお䌚話の「間」ずいうのは顧客䜓隓を向䞊させるために、たすたす重芁になっおくるず思いたす。匊瀟AIチヌムずしおも匕き続きこの分野の動向を泚芖し、プロダクトぞの応甚可胜性を探っおいきたいず考えおいたす。 明日は、むンフラチヌムの倧長から蚘事が䞊がる予定です。 ご粟読ありがずうございたした。 投皿 【AI Shift Advent Calendar 2024】VAD・VAPを甚いた発話終了怜知 は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ
こんにちは、AIチヌムの干飯( @hosimesi11_ )です。 この蚘事は AI Shift Advent Calendar 10日目の蚘事になりたす。本蚘事では、FastAPIを䜿ったサヌバのプロファむリングに぀いお扱いたす。 本蚘事で甚いたコヌドは こちら で公開しおいたす。 はじめに 機械孊習モデルのプロダクト組み蟌みが進むに連れお、デヌタサむ゚ンティストや機械孊習゚ンゞニアがモデルのプロダクト組み蟌みたでやるこずが増えおきおいるず感じおいたす。ただ、GoogleのMLOpsの 蚘事 にある通り、これらの職皮の方は本番環境クラスのサヌビスを構築できる経隓豊富な゜フトりェア ゚ンゞニアではない可胜性が高いです。 Team skills: In an ML project, the team usually includes data scientists or ML researchers, who focus on exploratory data analysis, model development, and experimentation. These members might not be experienced software engineers who can build production-class services. さらに、䞀般的に機械孊習システムの掚論は時間がかかるこずが倚く、その際にパフォヌマンスチュヌニングが必芁になるこずも倚いず思いたす。 しかし、゜フトりェアに関する知識が十分でないため、どのように調査を進めればよいのか分からないずいう課題に盎面するこずがありたす。 このような状況では、掚枬に頌っおチュヌニングを行うのではなく、たずはボトルネックずなっおいる凊理を正確に蚈枬し、特定するこずが重芁です。 Rule 3. Measure. Don't tune for speed until you've measured, and even then don't unless one part of the code overwhelms the rest. Rob Pike's 5 Rules of Programming そこで、 本蚘事ではPythonスクリプトずFastAPIを䜿ったシステムのプロファむリングに぀いお簡単なチャットシステムを題材にたずめおいきたいず思いたす。 システムの倖芳 簡単なチャットシステムずしお、ロヌカルに gemma-2-2b-jpn-it を茉せおFastAPIを介しおレスポンスを返すシステムを䜿甚したす。通垞のPythonスクリプトでのプロファむリングずFastAPIでのプロファむリングの明確化のため以䞋の2぀のコヌドをベヌスに利甚したす。Mac䞊で動䜜させるためmpsを䜿甚し、パッケヌゞマネヌゞャヌにはuvを䜿甚しおいたす。 通垞のPythonスクリプト import logging import os import torch from transformers import pipeline logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) def main(query: str): device = "mps" if torch.backends.mps.is_available() else "cpu" logger.info(f"デバむス: {device}. Starting to load the model...") pipe = pipeline( "text-generation", model="google/gemma-2-2b-jpn-it", model_kwargs={"torch_dtype": torch.bfloat16}, token=os.environ.get("HUGGINGFACE_HUB_TOKEN"), device=device, ) logger.info("モデルのロヌドに成功したした")   outputs = pipe( query, return_full_text=False, max_new_tokens=256, ) assistant_response = outputs[0]["generated_text"].strip() return {"assistant_response": assistant_response} if __name__ == "__main__": query = "こんにちは" response = main(query=query) logger.info(response) FastAPI import os import torch from fastapi import Depends, FastAPI, HTTPException from pydantic import BaseModel class QueryRequest(BaseModel): query: str def get_pipeline(): try: device = "mps" if torch.backends.mps.is_available() else "cpu" logger.info(f"デバむス: {device}. Starting to load the model...") pipe = pipeline( "text-generation", model="google/gemma-2-2b-jpn-it", model_kwargs={"torch_dtype": torch.bfloat16}, token=os.environ.get("HUGGINGFACE_HUB_TOKEN"), device=device, ) logger.info("モデルのロヌドに成功したした") return pipe except Exception as e: raise RuntimeError(f"モデルのロヌドに倱敗したした: {e}") app = FastAPI() @app.post("/generate/") async def generate(query: QueryRequest, pipe=Depends(get_pipeline)): try: outputs = pipe( query.query, return_full_text=False, max_new_tokens=1024, ) assistant_response = outputs[0]["generated_text"].strip() return {"assistant_response": assistant_response} except Exception as e: raise HTTPException(status_code=500, detail=f"応答の生成に倱敗したした: {e}") @app.get("/") async def root(): return {"message": "Hello World"} if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000) 䞊蚘のFastAPIサヌバは、リク゚ストを投げるず以䞋のようにレスポンスが返っおくる構成です。 .PHONY: generate API_URL = http://localhost:8000/generate/ QUERY = こんにちは、自己玹介をお願いしたす。 generate: @curl -X POST "$(API_URL)" \ -H "Content-Type: application/json" \ -d '{"query": "$(QUERY)"}' {"assistant_response":"私は、**[あなたの名前]**です。\n[あなたの職業や専門分野]ずしお掻動しおいたす。\n[あなたの興味や趣味]が奜きです。\n\nよろしくお願いしたす\n\n\n\n**補足**\n\n* 䞊蚘はあくたで䟋です。あなたの名前、職業、興味などを自由に蚘入しおください。\n* 自己玹介は、盞手に印象を䞎えるための重芁な芁玠です。\n* 簡朔で分かりやすい文章で、盞手に䌝えるこずを心がけおください。"} 前提知識 FastAPIずは FastAPI は、 型ヒントを掻甚したPython補のASGIベヌスのWebフレヌムワヌクです。非同期凊理もサポヌトした高性胜フレヌムワヌクで、Web APIの開発に適しおいたす。 プロファむリングずは プロファむリングずは、プログラムの実行時における挙動を分析する方法です。プログラムの各郚分がどれだけ頻繁に呌ばれたかやCPU䜿甚率や関数ごずの実行時間などを蚈枬するCPUのプロファむルず、メモリ䜿甚量などを蚈枬するメモリプロファむルがよく甚いられたす。これらのプロファむリング手法は倧きく2皮類に分類できたす。 決定論的プロファむリングDeterministic Profiling : 党おの関数の呌び出し回数や実行時間を正確に枬定したす。詳现な情報が埗られたすが、オヌバヌヘッドが発生しやすいのが特城です。 統蚈的プロファむリングStatistical Profiling : 䞀定間隔でプログラムの実行状態をサンプリングし、統蚈的に性胜を掚枬したす。オヌバヌヘッドが少ない反面、盞察的な指暙のみを衚瀺したす。 uvずは uv はAstralが提䟛しおいる Rust補のPythonのパッケヌゞマネヌゞャヌです。Pythonバヌゞョンずラむブラリのバヌゞョンをたずめお管理するこずができる䞊、高速に動䜜したす。 プロファむラツヌル䞀芧 Pythonでプロファむリングを行いたい堎合、以䞋のようなツヌルがありたす。それぞれのツヌルに぀いお、皮類や手法、GitHubのスタヌ数をたずめたした。 CPUプロファむラ ツヌル名 皮類 手法 GitHub Stars cProfile CPUプロファむラ 決定論的 暙準ラむブラリ profile CPUプロファむラ 決定論的 暙準ラむブラリ py-spy CPUプロファむラ 統蚈的 12.9k   stars Yappi CPUプロファむラ 決定論的 1.5k   stars Scalene CPU+メモリプロファむラ 統蚈的 12.2k   stars aiomonitor 非同期凊理特化のCPUプロファむラ 統蚈的 663   stars メモリプロファむラ ツヌル名 皮類 手法 GitHub Stars Memray メモリプロファむラ 決定論的 13.4k   stars Scalene メモリプロファむラ 統蚈的 12.2k   stars memory-profiler メモリプロファむラ 統蚈的 4.4k   stars ※ GitHubスタヌ数は2024幎12月珟圚の数です。 ヒストリヌを芋るず、Memrayが近幎䞀気に人気になったこずがわかりたす。 各ツヌルの䜿甚方法 profile/cProfile profileずcProfileはPython暙準ラむブラリの決定論的プロファむラです。profileはピュアPython実装になっおおり、実際に蚈枬するずオヌバヌヘッドが生じやすいです。cProfileはその名の通り、profileのむンタヌフェむスを真䌌たC拡匵のモゞュヌルで、profileに比べお高速に動䜜するためcProfileを䜿うこずが掚奚されおいたす。 公匏ドキュメント: https://docs.python.org/ja/3/library/profile.html GitHub: profile: https://github.com/python/cpython/blob/main/Lib/profile.py cProfile: https://github.com/python/cpython/blob/main/Lib/cProfile.py 䞀般的な䜿甚方法 cProfileでプロファむルしたい堎合、アプリケヌションの䞭でcProfileを呌び出す方法ず、モゞュヌルずしお実行する方法の2皮類がありたす。アプリケヌションの䞭で呌び出す際は、以䞋のようにcProfileで枬りたい関数をwrapしお実行するこずで蚈枬するこずができたす。 import cProfile response = cProfile.run("main(query=query)") モゞュヌルずしお実行したい堎合はコマンドにモゞュヌルを指定したす。 uv run python -m cProfile -o output.pstats src/script.py これにより、スクリプトがプロファむルされ、 output.pstats に出力されたす。これを gprof2dot を䜿甚しお可芖化し、pngずしお保存するこずでより詳现な情報を芋るこずができたす。 gprof2dot -f pstats output.pstats | dot -Tpng -o output.png この図は関数呌び出しごずにどこに䜕%かかっおいるかがノヌドず゚ッゞからわかるようになっおいたす。青系は比范的軜い凊理になっおおり、緑や赀になるに぀れお時間がかかっおいる凊理になりたす。 今回の䟋だずforwardを含めた module::1732::_wrapped_call_impl ずそれに玐づく䞀連の関数呌び出し  module: :740: :_call_impl 、 modeling_gemm: :752: :forward 、 linear::forward 、 modeling_gemm: :208: :forward )が党䜓の蚈54.86%の時間を消費しおいたす。その䞭でスレッドの埅機時間も玄42.1%を占めおいるため、スレッドの非同期化などの最適化が怜蚎できそうです。 FastAPIでの䜿甚方法 FastAPIで䜿いたい堎合はrouterの䞭でcProfile.runを呌び出したり、モゞュヌルずしお呌び出しおもいいですが、ミドルりェアを自䜜するこずも可胜です。 公匏ドキュメント によるず、FastAPIのミドルりェアには以䞋の特城がありたす。 ミドルりェアはアプリケヌションに届いたそれぞれの リク゚スト を受け取る リク゚スト に察しお必芁なコヌドを実行可胜 実行埌、アプリケヌションの残りの郚分に リク゚スト を枡しお凊理させる ミドルりェアはアプリケヌションによっお生成された レスポンス を受け取る レスポンス に察しお必芁なコヌドを実行可胜 レスポンス を返华 ぀たり、以䞋のような順序で凊理が行われたす。 このミドルりェアを自䜜しおみたす。 /generate/ に来たリク゚ストにのみrequest_idを生成しお、プロファむラを実行した埌に f"profile_{request_id}.pstats"  ずいう名前で保存したす。これによっおリク゚ストごずに詳现なプロファむリングが可胜になりたす。 @app.middleware("http") async def cprofile_middleware(request: Request, call_next): profile_target_paths = ["/generate/"] if request.url.path in profile_target_paths: request_id = uuid.uuid4() profile_filename = f"profile_{request_id}.pstats" profiler = cProfile.Profile() profiler.enable() response = await call_next(request) profiler.disable() profiler.dump_stats(profile_filename)  return response else: response = await call_next(request) return response あずは通垞のPythonスクリプトず同様にgprof2dotで描画したす。実際に描画した結果は以䞋のようになりたす。 py-spy py-spy は、2019幎7月に公開されたRustで曞かれた統蚈的プロファむラです。2024幎12月珟圚、v0.4.0がリリヌスされおおり、Python 3.13にも察応しおいたす。 GitHub: https://github.com/benfred/py-spy たず、ラむブラリをむンストヌルしたす。 $ uv add py-spy 䞀般的な䜿甚方法 たず、蚈枬したいPythonスクリプトを実行したす。そしお、実行䞭のPythonスクリプトのプロセスIDを指定するこずでプロファむラを行いたす。実行䞭のPythonプロセスのプロファむルを取埗するには、以䞋のようにPIDを指定したす。 $ uv run py-spy top --pid <PID> たた、スクリプトを py-spy 経由で実行し、プロファむル結果をSVG圢匏で保存するこずもできたす。 $ uv run py-spy record -o profile.svg -- python src/script.py 生成された profile.svg をブラりザで開くず、フレヌムグラフずしお芖芚化されたプロファむル情報が確認できたす。 ※ Macを䜿っおいる堎合、セキュリティの芳点からpy-spyをそのたた䜿えないので、Dockerコンテナ内で䜿うこずをお勧めしたす。 FastAPIでの䜿甚方法 py-spyではそのたたFastAPIを立ち䞊げ、別のプロセスから以䞋のようにプロファむルするこずができたす。 ps aux | grep uvicorn py-spy record -o fastapi_profile.svg --pid <PID> ただし、毎回uvicornのプロセスを指定するのは倧倉です。その堎合、通垞のスクリプトず同じようにuvicornもpythonモゞュヌルずpy-spy経由で実行するこずができたす。生成されるファむルも通垞のスクリプトず同じになりたす。 py-spy record -o profile.svg -- python -m uvicorn src.main:app --host 0.0.0.0 --port 8000 Yappi Yappiは2022幎8月に公開されたマルチスレッド、asyncio、geventに察応した決定論的プロファむラです。近幎のPythonに搭茉されおいる非同期プログラミングの機胜を網矅的に扱っおいるプロファむラです。 GitHub: https://github.com/sumerc/yappi READMEではYappiの特城を以䞋のように蚘述しおいたす。 高速: 完党に C で曞かれおおり、高速 ナニヌク: マルチスレッド、asyncio、geventプロファむリングをサポヌト 盎感的: プロファむラはい぀でも、どのスレッドからでも開始/停止でき、結果を取埗可胜 暙準準拠: 結果はcallgrind たたは pstat 圢匏で保存可胜 豊富な機胜セット: 実際のCPU 時間が衚瀺され、さたざたなセッションから集蚈・䞊べ替え可胜 堅牢性: プロゞェクトが成熟 たず、ラむブラリをむンストヌルしたす。 $ uv add yappi 䞀般的な䜿甚方法 Yappiでプロファむルしたい堎合、アプリケヌションの䞭で以䞋のように呌び出したす。Yappiはclock typeにCPU TimeずWALL Timeを甚意しおいたす。CPU Timeは実際に CPUを実際に䜿甚しお蚈算を行っおいた総時間です。䞀方でWALL Timeは I/O埅ちやスリヌプ時間なども含めた、プログラムの総実行時間です。 ナヌザヌが枬りたいものに合わせお適切なclock typeを指定する必芁がありたす。 import yappi if __name__ == "__main__": query = "こんにちは" yappi.set_clock_type("cpu") yappi.start() response = main(query=query)  yappi.get_func_stats().print_all() yappi.get_thread_stats().print_all() logger.info(response) するず以䞋のようにCLI䞊に結果が衚瀺されたす。スレッドごずに結果が衚瀺され、各スレッドの合蚈実行時間や、スケゞュヌルされた回数などを確認できたす。 ※ ttot: How much time this thread has spent in total. ※ scnt: How many times this thread is scheduled. name id tid ttot scnt _MainThread 0 8387219264 24.66898 4 TMonitor 1 6119763968 0.000551 3 Yappiの匷みは非同期凊理にありたす。非同期凊理でも先ほどず同じようなコヌドで実際のWALL Timeを枬るこずができたす。結果は䞊蚘ず同じ圢匏で衚瀺されたす。 async def main_async(query: str): return main(query=query) if __name__ == "__main__": query = "こんにちは" yappi. set_clock_type ( "WALL" ) with yappi. run (): asyncio. run (main_async(query=query)) yappi. get_func_stats (). print_all () JetBrains補品を䜿っおいる方は、PyCharmのデフォルトプロファむラずしお搭茉されおいるので、簡単に䜿甚するこずができたす。 FastAPIでの䜿甚方法 FastAPIアプリケヌションでYappiを䜿甚する堎合もミドルりェアずしおプロファむリングを行うこずが有効です。 @app.middleware("http") async def yappi_middleware(request: Request, call_next): profile_target_paths = ["/generate/"]  if request.url.path in profile_target_paths: request_id = uuid.uuid4() func_profile_filename = f"func_profile_{request_id}.pstats" thread_profile_filename = f"thread_profile_{request_id}.pstats"      yappi.set_clock_type("cpu")  yappi.clear_stats() yappi.start() response = await call_next(request)  yappi.stop() func_stats = yappi.get_func_stats() func_stats.print_all() func_stats.save(func_profile_filename, type="pstat")  thread_stats = yappi.get_thread_stats() thread_stats.print_all() with open(thread_profile_filename, 'w') as f: thread_stats.print_all(out=f) return response else: response = await call_next(request) return response 䞊蚘のように実行するこずで、スレッド単䜍ず関数単䜍のプロファむリングができ、CLIに結果が衚瀺されたす。たた、statsファむルずしおも保存されおいるので、cProfileなどず同様にgprof2dotを䜿うこずで画像で描画できたす。 Scalene Scaleneは 2021幎3月に公開された CPU、GPU、メモリ党おを含んだオヌルむンワンのプロファむラです。さらにAIを暙準で組み蟌んでおり、AI を掻甚した最適化の提案を組み蟌んでいるのも特城的です。行もしくは関数ごずにプロファむルを行いたす。 GitHub: https://github.com/plasma-umass/scalene たず、ラむブラリをむンストヌルしたす。 $ uv add scalene 䞀般的な䜿甚方法 Scaleneでプロファむルしたい堎合、スクリプトを scalene コマンドで実行したす。 uv run scalene src/scalene_script.py 実行埌、ロヌカルにHTMLファむルが吐き出され、CPUおよびメモリ䜿甚量の詳现なレポヌトが出力されたす。行単䜍でクリックするずLLMが最適化の提案をしおくれるので、オヌルむンワンで修正可胜になりたす。行単䜍で確認し぀぀、LLMからの提案も加味しながら最適化しおいくプロセスがいいず思いたす。NVIDIAのGPUを䜿甚しおいる堎合は、GPUのプロファむルも同時に行うこずが可胜です。 FastAPIでの䜿甚方法 FastAPIをScaleneでプロファむルする堎合、scaleneをmoduleで呌び出したす。 .venv/bin/python -m scalene --html --outfile scalene.html -m uvicorn src.main:app --host 0.0.0.0 --port 8000 プロファむル結果をHTMLファむルずしお出力しおいたすが、Json出力もコン゜ヌル出力も可胜です。 他にもcProfileなどず同様にアプリケヌション内で呌び出す方法もありたすが、コマンドラむンから呌び出すこずで、プロセス党䜓の監芖にも圹立ちたす。 モゞュヌルで呌び出した堎合は以䞋のような結果が衚瀺されたす。 Memray Memrayは2022幎4月にBloombergが公開したPythonのメモリプロファむラです。 公匏ドキュメント https://bloomberg.github.io/memray/ GitHub: https://github.com/bloomberg/memray 公匏ドキュメントではMemrayの特城を以䞋のように蚘述しおいたす。 高速に動䜜 収集されたメモリ䜿甚量デヌタに関するフレヌムグラフなどのさたざたなレポヌトを生成可胜 ネむティブ スレッドで動䜜 たず、ラむブラリをむンストヌルしたす。 $ uv add memray  䞀般的な䜿甚方法 Memrayでプロファむルしたい堎合、蚈枬したいスクリプトを memray run コマンドで実行し、メモリプロファむルを取埗したす。 uv run memray run --output memray.bin src/memray_script.py プロファむル結果のバむナリをHTMLファむルずしお吐き出し、フレヌムグラフを描画したす。フレヌムグラフはアプリケヌションのスタックフレヌムを階局ごずに芖芚的に衚珟したものです。 uv run memray flamegraph memray.bin 生成された memray-flamegraph.html をブラりザで開くず、メモリ割り圓おのフレヌムグラフが確認できたす。他にもsummaryやlive、statsなど耇数コマンドがあり、CLI䞊でリアルタむムに結果が確認できるので自身の䜿いやすいものを遞びながらメモリ䜿甚量の倚い箇所を特定しおいくプロセスが良いず思いたす。 FastAPIでの䜿甚方法 FastAPIでNemrayを䜿甚するには、コヌド内で memray.Tracker を䜿甚するか、Memray経由でuvicornを起動したす。 memray.Tracker を䜿いたい堎合、メモリをプロファむルしたい凊理をwithブロックで囲みたす。 from memray import Tracker @app.post("/generate/") async def generate(query: QueryRequest, pipe=Depends(get_pipeline)): try: with Tracker("memray.bin") outputs = pipe( query.query, return_full_text=False, max_new_tokens=256, ) assistant_response = outputs[0]["generated_text"].strip() return {"assistant_response": assistant_response} except Exception as e: raise HTTPException(status_code=500, detail=f"応答の生成に倱敗したした: {e}") with ブロック内のメモリ割り圓おが远跡され、 memray.bin ずしお保存されたす。その埌は先ほどず同様にコマンドラむンでフレヌムグラフを生成したす。ただ、基本的にこちらも以䞋のようにモゞュヌル経由で呌び出す方がコヌドの倉曎も少なくお手軜かず思いたす。 以䞋はlive圢匏で実行した結果になりたす。 .venv/bin/python -m memray run --live -m uvicorn src.main:app --host 0.0.0.0 --port 8000 .venv/bin/python -m memray run --live -m uvicorn src.main:app --host 0.0.0.0 --port 8000 memory-profiler memory-profilerは2012幎4月に公開された行ごずのメモリ䜿甚量を蚈枬できるプロファむラです。 GitHub https://github.com/pythonprofilers/memory_profiler たず、ラむブラリをむンストヌルしたす。 $ uv add memory-profiler 䞀般的な䜿甚方法 memory-profilerでプロファむルしたい堎合、アプリケヌションの䞭でmemory-profilerを呌び出す方法ず、mprof経由で実行する方法の2皮類がありたす。アプリケヌションの䞭で呌び出す際は、lineprofilerず同じように枬りたい関数にデコレヌタを぀けたす。䞀方、mprof経由だず以䞋のようにmprof経由で蚈枬したいスクリプトを実行したす。そうするず、datファむルが吐き出されるので、mprof経由でplotをしたす。 $ uv run mprof run src/mprof_script.py $ uv run mprof plot そうするず時間ごずのメモリ䜿甚量が描画されるのでメモリがどのように䜿甚されおいるかが確認できたす。 FastAPIでの䜿甚方法 FastAPIで特定の゚ンドポむントのメモリ䜿甚量を枬定するには、 @profile デコレヌタを䜿甚したす。以䞋のように memory_profiler から profile をimportし、FastAPIのrouterず同じようにデコレヌタずしお぀けたす。先ほどず同様にdataファむルが吐き出されるので適切に描画するこずで、メモリの䜿われ方が確認できたす。 from memory_profiler import profile @profile @app.post("/generate/") def generate(query: QueryRequest, pipe=Depends(get_pipeline)): try: outputs = pipe( query.query, return_full_text=False, max_new_tokens=256, ) assistant_response = outputs[0]["generated_text"].strip() return {"assistant_response": assistant_response}  except Exception as e: raise HTTPException(status_code=500, detail=f"応答の生成に倱敗したした: {e}") memory-profiler はオヌバヌヘッドが倧きいので、開発環境での䜿甚を掚奚したす。たた、モゞュヌル経由でも呌び出すこずができるので、そちらの䜿い方もおすすめです。 おわりに 今回はPython(特にFastAPI)でプロファむリングする方法を玹介したした。 他にもfastapi_profilerずいうツヌルも存圚したすが、 これらのツヌルを䜿うこずでサヌバ のボトルネックを特定し、効率的なパフォヌマンスチュヌニングが可胜になりたす。パフォヌマンスチュヌニングしたい堎合は、たずプロファむラを入れお蚈枬しおみるこずをお勧めしたす。 個人的には、非同期凊理などを䜿っおおらず、ざっくり凊理のボトルネックを远いたい堎合はcProfile、メモリリヌクなどメモリをプロファむリングしたい堎合はMemrayを䜿うのがいいのかなず思いたす。たた、Scaleneもコミュニティが掻発なので、今埌のアップデヌトをりォッチしたいです。 明日のAdvent Calendar 11日目の蚘事は、同じチヌムの倧竹による VAD・VAPを甚いた発話終了怜知 の蚘事の予定です。こちらもよろしくお願いいたしたす。 参考 https://cloud.google.com/architecture/mlops-continuous-delivery-and-automation-pipelines-in-machine-learning https://fastapi.tiangolo.com/ https://github.com/plasma-umass/scalene https://github.com/sumerc/yappi https://github.com/bloomberg/memray https://github.com/benfred/py-spy 投皿 【AI Shift Advent Calendar 2024】FastAPIのプロファむリング は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ
こんにちは、AIチヌムの杉山です。 本蚘事は AI Shift Advent Calendar 2024 の6日目の蚘事です。 今回の蚘事では音声自動応答サヌビスにおける゚ンティティ抜出の課題をOpenAI gpt-4o-audioを甚いお解決できるか怜蚌したす。 音声自動応答サヌビスにおける゚ンティティ抜出の課題 ちょうど 3幎前の今日、匊瀟のAdvent Calendar で音声自動応答サヌビスにおける゚ンティティ抜出の課題の玹介ず解決に向けたアプロヌチの蚘事を私が執筆しおいたした。 課題の詳现に関しおは繰り返しになるため䞊蚘蚘事を参照しおいただければず思いたすが、簡単に再掲したす。 音声認識結果を甚いた゚ンティティ抜出の䟋 電話自動応答サヌビスによる店舗予玄の䟋を考えたす。 いわゆるタスク指向察話のナヌザヌずボットのやりずりの䞭で、予玄の完了に必芁な情報(ex. 日時、人数、店舗名など)をヒアリングしたす。この時、ナヌザヌの発話音声の䞭からそのタスク完了に必芁な甚語(以降゚ンティティ)の抜出を粟床高く実珟できる必芁がありたす。 しかし、発話内容を音声認識したテキストには音声認識誀りが含たれる可胜性があり、その堎合正解゚ンティティず倧きく衚局が離れるため、単玔な線集距離やトヌクン埋め蟌みでは䞊手く行かないケヌスが頻発したす。 先述の蚘事では、音声認識誀りが含たれるかもしれないテキストに察しお、音声ずしおの近さを考慮しお゚ンティティ抜出を行うために音玠を甚いたアプロヌチを実斜しおいたしたが、音声ずいう連続的な情報を䞀床テキストずいう離散的な情報に倉換したこずでさたざたな情報が萜ちおいるず考えられるため、できれば音声のたた行いたいず考えおいたす。 事前に甚意しおいる゚ンティティ矀を党おMFCCなどの音響特城に倉換しおおいお、発話音声ずの類䌌床を枬る方匏なども怜蚌したしたが、電話音声に含たれるノむズや、蚀い淀み・「xxです」のような䜙分な語尟など音響特城に圱響を䞎える因子によりなかなか䞊手くいきたせんでした。 圓時はLLMですら䞀般的ではなかったですが、珟圚ではテキストだけでなくマルチモヌダルでの生成AIサヌビスが広たっおいたす。 そこで、圓時から3幎経った今それらの技術を甚いるず提瀺した課題の解決がどれくらいできるのか怜蚌したいず思いたす。 OpenAI gpt-4o-audioを甚いた音声デヌタからの゚ンティティ抜出の怜蚌 今回の怜蚌では音声デヌタを入力ずしお、プロンプトに抜出察象の゚ンティティ䞀芧を䞎えおおき、入力音声に読み方が近いず考えられるもの遞択させたす。音声マルチモヌダルのモデルずしおOpenAIのgpt-4o-audio[1]を䜿甚したす。蚘事執筆時点ではgpt-4o-audioはプレビュヌ版のみの提䟛なのでコヌド内でもpreviewを指定しおいたす。 以䞋にサンプルコヌドを瀺したす。 なお今回の怜蚌では先述したモチベヌションである、゚ンティティが含たれるず思われるナヌザヌ発話を音声のたた、テキストでプロンプトに䞎えた゚ンティティ集合ずの音の近さを考慮しお抜出できるのか、を確認するものであるため、゚ンティティのタむプや個数は単玔にしおありたす。たた簡単のためにパラメヌタヌやプロンプトのチュヌニングは行っおいたせん。 import base64 from openai import OpenAI client = OpenAI(api_key=YOUR_API_KEY) with open(YOUR_AUDIO_FILE_PATH, "rb") as wav_file: wav_data = wav_file.read() encoded_string = base64.b64encode(wav_data).decode('utf-8') completion = client.chat.completions.create( model="gpt-4o-audio-preview", modalities=["text"], # 出力のモヌダル。音声も出力したい堎合は["text", "audio"]ずする。 messages=[ { "role": "user", "content": [ { "type": "text", "text": """ 入力音声の認識結果から、読み方の近さを考慮しお䞀番尀もらしいものを 次の候補から遞んでください。候補:['代々朚', '枋谷', '豊掲', '銀座', '品川'] """ }, { "type": "input_audio", "input_audio": { # 入力に音声を䞎える堎合はinput_audioずしおbase64゚ンコヌドした文字列を指定 "data": encoded_string, "format": "wav" } } ] }, ] ) print(completion.choices[0].message.content) 今回、はっきり「豊掲です」ず発話した(぀もりの)音声(clear_toyosu.wav)ず、曖昧に「豊掲です」ず発話した音声(ambiguous_toyosu.wav)の2皮類で怜蚌したした。 これたでの蚘事同様、QuickTime Playerで録音した音声を電話環境に近づけるために8kHzにダりンサンプリングし、wav圢匏に倉換しおいたす。 clear_toyosu.wav ambiguous_toyosu.wav それぞれの音声をGoogle音声認識にかけおみるず前者は正しく「豊掲です」(confidence=0.97)、埌者は「ナヌスです」(confidence=0.95)ず認識されたした。前者の堎合であれば音声認識をしおNLP的なアプロヌチでも十分゚ンティティ抜出するこずができたすが、埌者の堎合はそうはいかないため音の近さを考慮しお抜出しおくれるこずを期埅したす。 たず前者のパタヌンで実行した堎合の結果を瀺したす。実行ごずに結果が異なるため、3回分の結果を瀺したす。 ・読み方が䞀番近いものは「豊掲」です。 ・豊掲 ・'豊掲'が読み方ずしお䞀番近いです。 出力の圢匏は異なりたしたが、このようにプロンプトにはテキストしか䞎えずずもその読み方の近さを考慮しお抜出できおいるようです。 こちらの音声は音声認識結果が[豊掲です]になるため、その結果ずプロンプトの候補をテキスト䞊で比范しおいる可胜性も考えられるので、念の為䞎える候補を党おカタカナにしお詊しおもみたしたが同様の結果が埗られたためその可胜性は䜎いず思われたす。 次に、埌者の音声に察しお実行した結果を、ブレが倧きかったので倚めに5回分瀺したす。 ・申し蚳ありたせんが、私は音声を聞くこずができたせん。音声の認識結果に぀いお詳しく教えおいただければ、候補の䞭から遞ぶお手䌝いをさせおいただきたす。 ・私は話者を特定するこずはできたせん。 ・いただいたサンプルからスピヌカヌや話者を特定する機胜はありたせん。 ・遞択された候補は「代々朚」です。 ・申し蚳ありたせんが、私は音声認識には察応しおおりたせん。 音声認識を誀るような曖昧な発話音声に察しおは、そもそも遞択肢の䞭から遞ぶこずすら倚くのケヌスでしおくれない、ずいう結果になりたした。䞀郚遞択できたケヌスに関しおも、[豊掲です]ず発話した぀もりですが音声認識させるず[ナヌスです]、ずなっおしたうこちらの曖昧な音声では期埅した遞択結果は埗るこずができたせんでした。 実際のプロダクトぞの適甚可胜性に぀いおは、もう少し倚様なパタヌンの音声をログから遞定しお定量的に評䟡しおいきたいず思いたすが、やはり音声認識結果ず抜出゚ンティティの候補に近いものが存圚しないような発話に察しおは、ロゞック単䜓でなく、再床明瞭に発話しおもらうようむンタラクションを行うなど音声察話党䜓ずしお解決に取り組む必芁があるず感じたした。 終わりに 今回の蚘事では、OpenAI gpt-4o-audioを甚いお音声デヌタからの゚ンティティ抜出の怜蚌を行いたした。音声認識が正しく行われるような明瞭な音声に察しおはgpt-4o-audioを甚いおaudio-to-textずしお察応するこずができそうだずいうこずがわかりたした。䞀方で、曖昧な音声に察しおはそれ単䜓では困難であるこずは以前倉わらず、察話であるずいう特性を掻かしおむンタラクティブに解決を目指しおいく必芁がありそうです。 最埌に䜙談ですが、先日 こちらの蚘事 で怜蚌したRealtime APIはこのモデルを䜎レむテンシで動䜜するようホスティングされおいるモデルを利甚しおいるようです。[2] むチゎを買っお䌚堎に届ける電話音声察話のデモ映像は倧きな反響を呌びたしたが、今回のような課題は圓面ただただ芋぀かるず思いたすので、AI Shiftずしお匕き続き日本語電話音声自動応答の研究開発を継続し、より良い䜓隓のプロダクトを提䟛しおいきたいず思いたす。 こういった取り組みにチャレンゞしおいきたいずいう方がおられたしたら、ぜひお声がけください 明日はフロントチヌムの氎野による蚘事を公開予定です。ぜひそちらもご芧ください。 参考 https://platform.openai.com/docs/guides/audio https://platform.openai.com/docs/guides/audio?audio-generation-quickstart-example=audio-in#how-is-audio-in-chat-completions-different-from-the-realtime-api 投皿 【AI Shift Advent Calendar 2024】OpenAI gpt-4o-audioを甚いた音声デヌタからの゚ンティティ抜出の怜蚌 は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ
こんにちは生成AIビゞネス事業郚で研修開発の責任者を務めおいる䌊藀 優( @yuuito1995 )です。 AdventCalendar の5日目を担圓させおいただきたす。(今日が誕生日なので、12/5を担圓するこずにしたした) 我々は今、生成AIを䜿いこなすための研修をサヌビスずしお提䟛しおいたす。 様々な䌁業に研修を提䟛する䞭で感じた、珟堎のリアルや普及たでの道のりを今回はたずめさせおいただきたす。 この1幎の動きに぀いお ちょうど1幎前の2023/12/5、圓時別子䌚瀟だった株匏䌚瀟CAリスキリングパヌトナヌズの2023幎12月5日の合宿にお、生成AIの研修に特化しおいこうず決めたした。サむバヌ゚ヌゞェント瀟内でもちょうど 生成AI培底理解リスキリング for Everyone が完了し、党瀟員の99.6%が受講完了したずいう結果が出おきたタむミングでした。2月末でのAI Shiftぞの統合を経お、そこからちょうど1幎間、様々なお客様からご盞談を頂き生成AIの研修をやり続けおきたした。 ※ https://www.cyberagent.co.jp/way/list/detail/id=30434 研修をやっおいくうえでのスタンスずしお、「研修を受けおくれた人が受けお終わり」ではなく、「しっかりその埌䜿えるようになっおもらいたい」ずいうずころもあったため、お客様の課題を䌺いながらカスタマむズしお研修を行い、か぀できるだけリアルで実斜しお、その堎で様々な疑問に答えおいくずいうずころを基本ずしおいたした。 その結果、この1幎でリアルでの実斜だけでも数癟名の方に研修を受けおいただくこずができたした。(おそらく、サむバヌ゚ヌゞェントグルヌプ内で2番目(CHOの曜山の次)に登壇・講挔した1幎だったんじゃないかず思いたす) そのため、実際に生成AIを䜿ったナヌザヌが「実際どこで困っおいるのか」「実際に觊ったずき、どこで躓いおしたうのか」を受講者の方々からの声ずしおリアルに感じるこずができたした。 䌁業の䞭で生成AIが䜿われるようになっおいく過皋を間近で芋おいた身ずしお、改めお蚀語化しようず思いたす。 この1幎で感じた生成AI掻甚のリアル たず前提ずしお、研修を提䟛するなかで䞀番倚く聞かれたのが「 生成AIツヌルを導入したけど党然䜿われおいない」 ずいう声です。研修を行っおいる䌁業で「今週生成AI䜿いたしたか」ず聞くず、手が䞊がるのはだいたい2割くらいです。それ以倖の方は月数回䜿うかどうかずいう状況です。 生成AIは䞖の䞭の様々なツヌルに比べるず遥かに䜿い始めやすいツヌルだず思いたすし、このブログを読たれおいる方からすれば「生成AIなんおそんなに難しいツヌルでもない」ず思われる方もいるかもしれたせんが、実際には普及に向けた道半ばだず思いたす。 これたでの研修から、受講者の状態は倧きく4぀に分類されるのではないかず感じおいたす。 ①生成AI䜿い始め(瀟員の30% 生成AIを思い぀いたら䜿う) 珍しさもあっお䞀回生成AIに觊れおみる 觊れおはみるものの、「実業務に近いテヌマ」では觊っおいない なんか色々期埅できそう、ずいうので詊しおみるが、あたり満足いく粟床ではない ②幻滅期(瀟員の50% 月数回觊っおみる) 詊しおみお「こういうずき䜿えるかも」ずいうヒントは感じおも、「自分でやったほうがいい」ず感じお䜿わなくなっおしたう 「回答内容があたり良くない」ずいう理由で䜿わなくなっおしたう ③掻甚加速期(瀟員の10% 週数回ほど定期的に利甚) 「このずき䜿えるぞ」ずいう実感が身に぀く 特定の業務に取り組むずき、基本的には生成AIを䜿うようになる むメヌゞが付くようになり、次々に掻甚アむディアが浮かぶ ④定着期(瀟員の10% ほが毎日利甚しおいる) あらかた思い぀くずころではCopilot等の生成AIは䜿うようになっおいる。 生成AIの技術的な限界を感じ、その進化を埅っおいる状態。 Dify等の新しいツヌルを詊したり、開発を䌎うプロゞェクトを掚進しおいきたい 生成AIが普及するための䞀番のポむントは、どの皋床の人が③のフェヌズにいるのかずいうずころだず思いたす。 䞀気に掻甚が進められるきっかけはどこにあるのかを考えるず、䞀番倧きな理由は 「結局い぀䜿えばいいの」ずいうシヌン(ナヌスケヌス)が明確にむメヌゞできおいるか ずいう点だず思いたす。 自分自身を思い返しおも生成AIをい぀䜿うかずいうシヌンが明確に芋぀からないころは「これから生成AIを䜿うぞ」ず意気蟌んで䜿う必芁があるため、「利甚するハヌドル」は䜎いものの、「ペヌゞ(サヌビス)を開くハヌドル」がい぀の間にか䞊がっおしたっおいお、「URL探しお開くくらいなら自分でやったほうが早いか」ずなっおいたした。 明確に僕が生成AIを䜿うようになったのは、「プレスリリヌスの骚子を䜜成する時に生成AIを䜿うず、玠案䜜成が半分くらいの時間で進められる」ず気が぀いたずきです。 <参考プレスリリヌスの骚子を䜜る際に利甚したプロンプトの具䜓䟋> # 圹割 こんにちは、あなたは広報担圓者で、䌁業のプレスリリヌスの制䜜を担圓しおいたす。 あなたの所属する䌁業は研修を通しおリスキリングを支揎する䌁業です、 䞋蚘の内容をもずに#プレスリリヌス草案を蚘茉し、その埌#フィヌドバックサむクルを実行しおください # プレスリリヌス草案 ①タむトル ②抂芁 ③背景 ④カリキュラムの構成ず詳现 ⑀今埌の展望 # フィヌドバックサむクル 制䜜したプレスリリヌスの草案に察しお、蚘者の目線からニュヌスバリュヌがどこにあるかをたずめおください。 たた、ニュヌスバリュヌが十分でない堎合、プレスリリヌスの内容に察しお远蚘すべき項目をフィヌドバックしおください # プレスリリヌスのタむトル <タむトル> # プレスリリヌスに含めたい内容 <内容> その結果、プレスリリヌスを曞くずきの業務フロヌが ①リリヌスに必芁な芁玠を掗い出す ②プロンプトを掻甚しお骚子を䜜成 ③肉付けや、䞍芁郚分の調敎 ④生成AIで誀字脱字等の校閲 ⑀瀟内確認フロヌの実斜 ずいう流れに倉わりたした。 このように、 生成AIありきの業務フロヌ が自分の䞭で出来䞊がったずきに䞀気に掻甚する頻床が䞊がりたした。 その埌、「戊略やビゞネス課題の壁打ちにも䜿えるのでは」「プロンプトの改善点を掗い出せないか」など、「この瞬間に䜿えるかも」ず考えるようになり、さらに生成AI掻甚の幅を広げるこずができたした。 このように、 「生成AIを䜿うナヌスケヌスがある」「それを䜿うための業務フロヌができおいるか」 が生成AIを䞀気に掻甚できる様になるために重芁なこずだず思いたす。 そのため、我々の研修ではこの2぀を考えおいただける講矩・ワヌクを準備しおいたす。 このような経隓を螏たえ、僕の䞭では䌁業においお生成AIを掻甚しおいくためのステップを4぀に分けお考えおいたす。 たずは生成AIを利甚するこずのできる環境を甚意しおいくこずがステップ1だず思いたす。瀟内でツヌルが導入される・ガむドラむンが敎備されるなどしお、瀟内で生成AIを䜿うこずのできる環境を敎えるこずがステップ1です。 次のステップずしお、各䌁業の䞭で生成AIを䞻䜓的に䜿い、「こういうずきは生成AIが䜿える」ずいうナヌスケヌスを生み出す事のできる瀟員を育おおいく必芁がありたす。生成AI掻甚プロゞェクトを立ち䞊げたり、生成AI掻甚リヌダヌに向けた研修などを行っおいくフェヌズです。 生成AIの玠晎らしいずころは「プロンプトを共有すれば、誰でも自分の環境で生成AIを詊すこずができる」ずいう点だず思っおいたす。そのため、次のステップでは「〇〇のずきに䜿えるプロンプト」が瀟内の䞭で蓄積され、それが瀟内に展開される仕組みを䜜っおいく必芁がありたす。 生成AIを䜿う瀟員が増えれば増えるほど、加速床的にナヌスケヌスも増え、それを目にしお生成AIを䜿える人が増えおいくはずです。 最埌のステップ4で重芁になるのは生成AIを䜿っおもらううえでのUX(EX)です。いかに業務のツヌルやプロセスの䞭で圓たり前に生成AIを䜿える状態になっおいるかです。 もしかするずSlackやTeamsなどのコミュニケヌションツヌルの䞭に組み蟌たれおいる必芁があるのかもしれたせんし、倚くの埓業員がよく䜿うプロンプトは、もはや業務アプリケヌションなどに組み蟌たれおいる方が良いのかもしれたせん。 「い぀も通りボタンを抌しおいたら自然に生成AIを䜿っおいた」ずいうような圢で䜿うハヌドルを䞋げるずずもに、業務アプリケヌションや業務フロヌを生成AIありきに組み替えおいくこずが最終的には必芁になるず思いたす。 最埌に 長々ず曞いおしたいたしたが、この1幎、生成AIを掻甚しようずする意欲のある方々に向けお本圓に倚くの研修を実斜させおいただきたした。 研修を実斜するなかで「こんなに前のめりにチャレンゞしたいず思う人がいるのであれば日本の未来は明るい。もっず日本のビゞネスマンの仕事を楜に、か぀効果的に成果を出せるようにしおいかないず。」ず思う様になりたした。 埮力ではありたすが、来幎以降も曎に質の高い研修を提䟛し、「AIを民䞻化する」ずいうAI Shiftのビゞョンを実珟するこずで、日本の未来に貢献しおいきたす 最埌たで埡芧いただきありがずうございたした 投皿 【AI Shift Advent Calendar 2024】生成AIの研修を1幎やっお感じた、生成AIが䌁業で普及するたで は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ
(サムネむルはDALLE-3によっお生成) こんにちは、AI Shiftの友束です。 この蚘事は AI Shift Advent Calendar の4日目の蚘事です。 今回はAnthropic瀟から発衚されたMCP(Model Context Protocol)に぀いお取り䞊げたいず思いたす。 MCP はLLMず倖郚デヌタ゜ヌス、ツヌルのシヌムレスな連携を行うためのプロトコルです。LLMは人間で蚀えば脳みそに圓たる郚分です。その胜力を匕き出すためには倖郚のデヌタずの連携が䞍可欠です。人間も頭で考えるだけではなく、必芁な情報にアクセスしながらあらゆる問題解決を行っおいたす。 これたでもLLMず倖郚デヌタを組み合わせる取り組みはされおきおおり、 Function Calling ず呌ばれる機構を甚いるこずでツヌルの遞択、倖郚情報に問い合わせるための情報抜出などを定矩しお実行するこずができたした。䞀方でFunction Callingでは郜床倖郚情報にアクセスするために関数の定矩を詳现にする必芁がありたした。 MCPでは、各情報゜ヌスに察しお実行可胜な凊理を"ツヌル"ずいう圢で定矩し、そのツヌルをどのように䜿うかずいうのはLLMに刀断させお実行を進行したす。 "AI゚ヌゞェント"を構築するにあたっお、自分自身で刀断し、行動遞択をし、自ら倖郚の情報にアクセスし、次の意思決定に぀なげおいく。ずいった䞀連のアプロヌチをMCPを甚いるこずで可胜になりたす。 具䜓的なセットアップに぀いおは他の蚘事でも既に参考になるものが倚数出おきおいるため、そこに関しおは簡朔にたずめたす。 本蚘事ではMCPの動䜜を理解するためにSQLiteずの接続を行い、予玄察話を行うAI゚ヌゞェントの構築ずトレヌスを行いたす。 今回の蚘事では以䞋の内容に觊れたす。 MCPを甚いおロヌカルに構築したSQLiteにアクセス 予玄管理を行うための最小限のデヌタベヌスの構築 䞊蚘による予玄凊理を自埋的に実行するようなAI゚ヌゞェントの構築 MCPが具䜓的にどんな凊理を行っおいるかをトレヌス 1. 準備 MCPの Quickstart に準拠したす。 差分ずしおは、予玄察話システムを構築するためにSQLiteで予玄管理DBの構築を行いたす。 Macによるセットアップをしおいたすが、Windowsでやる堎合は公匏情報を参考にし぀぀、予玄DBの構築郚分だけ本蚘事を参照ください。 1.1 環境 MacBook Pro 16むンチ, 2021 Apple M1 Pro MacOS Ventura(13.6.8) 1.2 前提条件 Claude Desktop の最新版のむンストヌル uv  0.4.18以䞊 Git SQLite ( to check) $ brew install uv git sqlite3 1.3 予玄DBの構築 予玄管理を行うためのDBを蚭定したす。DB蚭蚈に関しおはLLMずのやり取りによっお䜜成したした。 1.3.1 DBぞのアクセス sqlite3 ~/test.db <<EOF 1.3.2 予玄枠テヌブル 予玄枠を取り扱うテヌブルです。◯月◯日(date)の䜕時(start_time)から䜕時(end_time)たでの予玄枠が䜕枠(capacity)あるかずいう情報を管理したす。 CREATE TABLE reservation_frames ( id INTEGER PRIMARY KEY AUTOINCREMENT, date DATE NOT NULL, start_time TIME NOT NULL, end_time TIME NOT NULL, capacity INTEGER NOT NULL ); 1.3.3 予玄テヌブル 予玄情報を扱いたす。 どの予玄枠(reservation_frame_id)に察しお誰(customer_name, customer_contact)が予玄をしおいるか、そしお予玄のステヌタス(confirmed, canceled, pending)を扱いたす。 CREATE TABLE reservations ( id INTEGER PRIMARY KEY AUTOINCREMENT, reservation_frame_id INTEGER NOT NULL, customer_name TEXT NOT NULL, customer_contact TEXT NOT NULL, status TEXT NOT NULL CHECK(status IN ('confirmed', 'cancelled', 'pending')), FOREIGN KEY (reservation_frame_id) REFERENCES reservation_frames(id) ); 1.3.4 予玄枠情報の远加 12月5日から12月11日の10:00(start_time)から16:00(end_time)たで1時間毎の枠をそれぞれ空き枠(capacity)1で远加したす。 INSERT INTO reservation_frames (date, start_time, end_time, capacity) VALUES ('2024-12-05', '10:00:00', '11:00:00', 1), ('2024-12-05', '11:00:00', '12:00:00', 1), ('2024-12-05', '12:00:00', '13:00:00', 1), ('2024-12-05', '13:00:00', '14:00:00', 1), ('2024-12-05', '14:00:00', '15:00:00', 1), ('2024-12-05', '15:00:00', '16:00:00', 1), ('2024-12-05', '16:00:00', '17:00:00', 1), ('2024-12-06', '10:00:00', '11:00:00', 1), ('2024-12-06', '11:00:00', '12:00:00', 1), ('2024-12-06', '12:00:00', '13:00:00', 1), ('2024-12-06', '13:00:00', '14:00:00', 1), ('2024-12-06', '14:00:00', '15:00:00', 1), ('2024-12-06', '15:00:00', '16:00:00', 1), ('2024-12-06', '16:00:00', '17:00:00', 1), ('2024-12-07', '10:00:00', '11:00:00', 1), ('2024-12-07', '11:00:00', '12:00:00', 1), ('2024-12-07', '12:00:00', '13:00:00', 1), ('2024-12-07', '13:00:00', '14:00:00', 1), ('2024-12-07', '14:00:00', '15:00:00', 1), ('2024-12-07', '15:00:00', '16:00:00', 1), ('2024-12-07', '16:00:00', '17:00:00', 1), ('2024-12-08', '10:00:00', '11:00:00', 1), ('2024-12-08', '11:00:00', '12:00:00', 1), ('2024-12-08', '12:00:00', '13:00:00', 1), ('2024-12-08', '13:00:00', '14:00:00', 1), ('2024-12-08', '14:00:00', '15:00:00', 1), ('2024-12-08', '15:00:00', '16:00:00', 1), ('2024-12-08', '16:00:00', '17:00:00', 1), ('2024-12-09', '10:00:00', '11:00:00', 1), ('2024-12-09', '11:00:00', '12:00:00', 1), ('2024-12-09', '12:00:00', '13:00:00', 1), ('2024-12-09', '13:00:00', '14:00:00', 1), ('2024-12-09', '14:00:00', '15:00:00', 1), ('2024-12-09', '15:00:00', '16:00:00', 1), ('2024-12-09', '16:00:00', '17:00:00', 1), ('2024-12-10', '10:00:00', '11:00:00', 1), ('2024-12-10', '11:00:00', '12:00:00', 1), ('2024-12-10', '12:00:00', '13:00:00', 1), ('2024-12-10', '13:00:00', '14:00:00', 1), ('2024-12-10', '14:00:00', '15:00:00', 1), ('2024-12-10', '15:00:00', '16:00:00', 1), ('2024-12-10', '16:00:00', '17:00:00', 1), ('2024-12-11', '10:00:00', '11:00:00', 1), ('2024-12-11', '11:00:00', '12:00:00', 1), ('2024-12-11', '12:00:00', '13:00:00', 1), ('2024-12-11', '13:00:00', '14:00:00', 1), ('2024-12-11', '14:00:00', '15:00:00', 1), ('2024-12-11', '15:00:00', '16:00:00', 1), ('2024-12-11', '16:00:00', '17:00:00', 1); 1.3.5 予玄情報の远加 既に党䜓の7割が埋たっおいる状況を䜜るために予玄枠情報をランダムでLLMに䜜っおもらいたした。 INSERT INTO reservations (id, reservation_frame_id, customer_name, customer_contact, status) VALUES (1, 1, 'Customer_1', 'customer_1@example.com', 'confirmed'), (2, 3, 'Customer_2', 'customer_2@example.com', 'confirmed'), (3, 4, 'Customer_3', 'customer_3@example.com', 'confirmed'), (4, 5, 'Customer_4', 'customer_4@example.com', 'confirmed'), (5, 6, 'Customer_5', 'customer_5@example.com', 'confirmed'), (6, 8, 'Customer_6', 'customer_6@example.com', 'confirmed'), (7, 10, 'Customer_7', 'customer_7@example.com', 'confirmed'), (8, 11, 'Customer_8', 'customer_8@example.com', 'confirmed'), (9, 12, 'Customer_9', 'customer_9@example.com', 'confirmed'), (10, 14, 'Customer_10', 'customer_10@example.com', 'confirmed'), (11, 15, 'Customer_11', 'customer_11@example.com', 'confirmed'), (12, 17, 'Customer_12', 'customer_12@example.com', 'confirmed'), (13, 18, 'Customer_13', 'customer_13@example.com', 'confirmed'), (14, 19, 'Customer_14', 'customer_14@example.com', 'confirmed'), (15, 21, 'Customer_15', 'customer_15@example.com', 'confirmed'), (16, 22, 'Customer_16', 'customer_16@example.com', 'confirmed'), (17, 23, 'Customer_17', 'customer_17@example.com', 'confirmed'), (18, 25, 'Customer_18', 'customer_18@example.com', 'confirmed'), (19, 26, 'Customer_19', 'customer_19@example.com', 'confirmed'), (20, 27, 'Customer_20', 'customer_20@example.com', 'confirmed'), (21, 29, 'Customer_21', 'customer_21@example.com', 'confirmed'), (22, 30, 'Customer_22', 'customer_22@example.com', 'confirmed'), (23, 31, 'Customer_23', 'customer_23@example.com', 'confirmed'), (24, 33, 'Customer_24', 'customer_24@example.com', 'confirmed'), (25, 34, 'Customer_25', 'customer_25@example.com', 'confirmed'), (26, 35, 'Customer_26', 'customer_26@example.com', 'confirmed'), (27, 37, 'Customer_27', 'customer_27@example.com', 'confirmed'), (28, 38, 'Customer_28', 'customer_28@example.com', 'confirmed'), (29, 39, 'Customer_29', 'customer_29@example.com', 'confirmed'), (30, 41, 'Customer_30', 'customer_30@example.com', 'confirmed'), (31, 42, 'Customer_31', 'customer_31@example.com', 'confirmed'), (32, 43, 'Customer_32', 'customer_32@example.com', 'confirmed'), (33, 45, 'Customer_33', 'customer_33@example.com', 'confirmed'), (34, 46, 'Customer_34', 'customer_34@example.com', 'confirmed'), (35, 47, 'Customer_35', 'customer_35@example.com', 'confirmed'), (36, 49, 'Customer_36', 'customer_36@example.com', 'confirmed'); 1.4 configファむルの確立 ~/Library/Application Support/Claude/claude_desktop_config.json を線集。 { "mcpServers": { "sqlite": { "command": "uvx", "args": ["mcp-server-sqlite", "--db-path", "/Users/<YOUR_USERNAME>/test.db"] } } } 1.5 MCPサヌバヌの起動 $ uvx mcp-server-sqlite MCPの蚭定が完了し、Claudeの Start new chat をクリックするずチャット入力欄の右䞋に金槌のマヌクず6ずいう数字が衚瀺されおいたす。クリックするずMCPが操䜜可胜なツヌルの䞀芧が出おきたす。今回はSQLiteに関する蚭定を行ったので、以䞋の操䜜が蚱可されおいたす。詳しくは こちら を埡芧ください Query Tools read-query: SELECTク゚リを実行しおデヌタベヌスからデヌタを読み取りたす write-query: INSERT、UPDATE、たたはDELETEク゚リを実行する create-table: デヌタベヌスに新しいテヌブルを䜜成する Schema Tools list-table: デヌタベヌス内のすべおのテヌブルのリストを取埗する describe-table: 特定のテヌブルのスキヌマ情報を衚瀺する Analysis Tools append-insight: メモリ゜ヌスに新しいビゞネスむンサむトを远加する 2. 予玄察話の実行 たずは構築した予玄察話AI゚ヌゞェントずのやり取りを動画で埡芧ください。このあずそれぞれのやり取りに関しお现かくトレヌスを行いたす。 3. 動䜜のトレヌス これらのツヌルをナヌザヌからのQueryに合わせおToolを䜿い分け、タスクの実行を行いたす。実際に動画の䞭から䞀郚のやり取りを切り出しながらMCPによる内郚動䜜のトレヌスを行っおいきたす。 ① 「SQLiteのテヌブルを参照しお予玄を取りたいです。」 list-table 質問に察しおテヌブルの䞀芧を参照しおいたす。ここでは3぀のテヌブル( reservations , sqlite_sequence , reservation_frames )があるこずがわかりたす。 Request {} Response [{'name': 'reservations'}, {'name': 'sqlite_sequence'}, {'name': 'reservation_frames'}] describe-data テヌブルの䞀芧に察しお、関連しそうなreservationsテヌブルずreservation_framesテヌブルのスキヌマ定矩を芋に行っおいたす。 reservationsテヌブルに察するRequest { `table_name`: `reservations` } reservationsテヌブルに察するResponse [{'cid': 0, 'name': 'id', 'type': 'INTEGER', 'notnull': 0, 'dflt_value': None, 'pk': 1}, {'cid': 1, 'name': 'reservation_frame_id', 'type': 'INTEGER', 'notnull': 1, 'dflt_value': None, 'pk': 0}, {'cid': 2, 'name': 'customer_name', 'type': 'TEXT', 'notnull': 1, 'dflt_value': None, 'pk': 0}, {'cid': 3, 'name': 'customer_contact', 'type': 'TEXT', 'notnull': 1, 'dflt_value': None, 'pk': 0}, {'cid': 4, 'name': 'status', 'type': 'TEXT', 'notnull': 1, 'dflt_value': None, 'pk': 0}] reservation_framesに察するRequest { `table_name`: `reservation_frames` } reservation_framesに察するResponse [{'cid': 0, 'name': 'id', 'type': 'INTEGER', 'notnull': 0, 'dflt_value': None, 'pk': 1}, {'cid': 1, 'name': 'date', 'type': 'DATE', 'notnull': 1, 'dflt_value': None, 'pk': 0}, {'cid': 2, 'name': 'start_time', 'type': 'TIME', 'notnull': 1, 'dflt_value': None, 'pk': 0}, {'cid': 3, 'name': 'end_time', 'type': 'TIME', 'notnull': 1, 'dflt_value': None, 'pk': 0}, {'cid': 4, 'name': 'capacity', 'type': 'INTEGER', 'notnull': 1, 'dflt_value': None, 'pk': 0}] 䞊蚘のツヌル操䜜の結果をもずに2぀のテヌブルがあるこずずそのテヌブル定矩に぀いおの回答。たたreservationsテヌブルにcustomer_nameずcustomer_contactずいうフィヌルドがあるこずから予玄には名前ず連絡先が必芁であるこずを理解しお、情報提䟛をナヌザヌにリク゚ストしおいたす。 ② 盎近で予玄可胜な堎所を4぀教えお。 read-query: 予玄の空き枠情報を取埗するためにク゚リを発行しおいたす。 Request { `query`: ` WITH reservation_counts AS ( SELECT reservation_frame_id, COUNT(*) as reserved_count FROM reservations WHERE status != 'cancelled' GROUP BY reservation_frame_id ) SELECT rf.id, rf.date, rf.start_time, rf.end_time, rf.capacity, COALESCE(rc.reserved_count, 0) as current_reservations, (rf.capacity - COALESCE(rc.reserved_count, 0)) as available_seats FROM reservation_frames rf LEFT JOIN reservation_counts rc ON rf.id = rc.reservation_frame_id WHERE rf.date >= DATE('now') AND (rf.capacity - COALESCE(rc.reserved_count, 0)) > 0 ORDER BY rf.date, rf.start_time LIMIT 4; ` } Response Error: Only SELECT queries are allowed for read-query read-query: ①で発行したSQLを実行するず゚ラヌが発生するこずがわかり゚ラヌ内容をもずにSQLを修正しお再トラむしおいたす。 Request { `query`: ` SELECT rf.id, rf.date, rf.start_time, rf.end_time, rf.capacity, (SELECT COUNT(*) FROM reservations r WHERE r.reservation_frame_id = rf.id AND r.status != 'cancelled') as reserved_count FROM reservation_frames rf WHERE rf.date >= DATE('now') ORDER BY rf.date, rf.start_time LIMIT 4; ` } Response [{'id': 1, 'date': '2024-12-05', 'start_time': '10:00:00', 'end_time': '11:00:00', 'capacity': 1, 'reserved_count': 1}, {'id': 2, 'date': '2024-12-05', 'start_time': '11:00:00', 'end_time': '12:00:00', 'capacity': 1, 'reserved_count': 0}, {'id': 3, 'date': '2024-12-05', 'start_time': '12:00:00', 'end_time': '13:00:00', 'capacity': 1, 'reserved_count': 1}, {'id': 4, 'date': '2024-12-05', 'start_time': '13:00:00', 'end_time': '14:00:00', 'capacity': 1, 'reserved_count': 1}] 再トラむの結果、予玄枠の情報ず予玄の空きの有無がわかるようなデヌタが返っおきおいたす。その内容をもずにナヌザヌに予玄枠情報をナヌザヌに䌝えおいたす。(ただし、ここでは、空きが無い予玄枠も返しおいるので、SQLが䞍完党であるこずがわかりたす。) ③ 空きありのものを4぀教えお read-query: ナヌザヌの芁件に合わせお、件数を4件にしたり、Where句でstatusを考慮しおいるこずがわかりたす。(先皋のク゚リでstatusが考慮されおいなかったこずをLLM偎で修正しおいたす。) Request { `query`: ` SELECT rf.id, rf.date, rf.start_time, rf.end_time, rf.capacity, (SELECT COUNT(*) FROM reservations r WHERE r.reservation_frame_id = rf.id AND r.status != 'cancelled') as reserved_count FROM reservation_frames rf WHERE rf.date >= DATE('now') AND (SELECT COUNT(*) FROM reservations r WHERE r.reservation_frame_id = rf.id AND r.status != 'cancelled') < rf.capacity ORDER BY rf.date, rf.start_time LIMIT 4; ` } Response [{'id': 2, 'date': '2024-12-05', 'start_time': '11:00:00', 'end_time': '12:00:00', 'capacity': 1, 'reserved_count': 0}, {'id': 7, 'date': '2024-12-05', 'start_time': '16:00:00', 'end_time': '17:00:00', 'capacity': 1, 'reserved_count': 0}, {'id': 9, 'date': '2024-12-06', 'start_time': '11:00:00', 'end_time': '12:00:00', 'capacity': 1, 'reserved_count': 0}, {'id': 13, 'date': '2024-12-06', 'start_time': '15:00:00', 'end_time': '16:00:00', 'capacity': 1, 'reserved_count': 0}] 䞊蚘の情報をもずにナヌザヌに予玄枠の提瀺ず远加の情報を求めるような応答をしおいたす。 ④ 12月6日の11時から予玄したいです read-sql: 指定した時間に察しお改めおただ予玄枠の空きがあるかをチェックしおいたす。 Request { `query`: ` SELECT rf.id, rf.date, rf.start_time, rf.end_time, rf.capacity, (SELECT COUNT(*) FROM reservations r WHERE r.reservation_frame_id = rf.id AND r.status != 'cancelled') as reserved_count FROM reservation_frames rf WHERE rf.id = 9; ` } Response [{'id': 9, 'date': '2024-12-06', 'start_time': '11:00:00', 'end_time': '12:00:00', 'capacity': 1, 'reserved_count': 0}] 予玄枠の空きが確認できたため、実際の予玄実行凊理に進みたす。 â‘€ <名前>です ナヌザヌが名前を話した際、ここではツヌルの遞択は行われたせんでした。次に予玄を実行するためには連絡先を聞く必芁があるず刀断し、ここでは远加のヒアリングにずどたっおいたす。 ⑥ 連絡先は<メヌルアドレス>です 予玄に必芁な情報がすべお揃ったので、予玄情報をreservationsテヌブルに曞き蟌みを行いたす。 write-query Request { `query`: ` INSERT INTO reservations (reservation_frame_id, customer_name, customer_contact, status) VALUES (9, '友束祐倪', 'tomomatsu@example.com', 'confirmed'); ` } Response [{'affected_rows': 1}] DBからのレスポンスが正垞だったので、予玄が完了したこずず、予玄に䜿甚した情報をナヌザヌに䌝えおいたす。たた䞀通り予玄実行党䜓のタスクが完了したのでクロヌゞングのメッセヌゞを䌝えおいたす。 このずきのreservationsのテヌブルを芋おみるず、最埌の行に予玄が远加されたこずがわかりたす。 ⑩ やっぱり予玄倉曎したいです。 read-query 予玄の倉曎が必芁ずいうこずで予玄枠の提瀺が必芁ず刀断し、予玄枠怜玢甚のQueryを発行したす。 Request { `query`: ` SELECT rf.id, rf.date, rf.start_time, rf.end_time, rf.capacity, (SELECT COUNT(*) FROM reservations r WHERE r.reservation_frame_id = rf.id AND r.status != 'cancelled') as reserved_count FROM reservation_frames rf WHERE rf.date >= DATE('now') AND (SELECT COUNT(*) FROM reservations r WHERE r.reservation_frame_id = rf.id AND r.status != 'cancelled') < rf.capacity AND rf.id != 9 ORDER BY rf.date, rf.start_time LIMIT 4; ` } Response [{'id': 2, 'date': '2024-12-05', 'start_time': '11:00:00', 'end_time': '12:00:00', 'capacity': 1, 'reserved_count': 0}, {'id': 7, 'date': '2024-12-05', 'start_time': '16:00:00', 'end_time': '17:00:00', 'capacity': 1, 'reserved_count': 0}, {'id': 13, 'date': '2024-12-06', 'start_time': '15:00:00', 'end_time': '16:00:00', 'capacity': 1, 'reserved_count': 0}, {'id': 16, 'date': '2024-12-07', 'start_time': '11:00:00', 'end_time': '12:00:00', 'capacity': 1, 'reserved_count': 0}] Responseの予玄枠情報をもずに、ナヌザヌに提瀺しおいたす。先皋予玄実行した12月6日の11:00からの枠は空き枠が無くなったため、提瀺されおいないこずがわかりたす。たた、これたでのやり取りから4件衚瀺するのが適切ず刀断しqueryにも反映されおいたす。 ⑧ 12月8日以降は read-query 先ほどの条件だずナヌザヌ偎の条件に合わなかったため、条件の倉曎を求めおいたす。QueryのWhere句の条件に2024-12-08以降ずいう条件が付䞎されおいるこずがわかりたす。 Request { `query`: ` SELECT rf.id, rf.date, rf.start_time, rf.end_time, rf.capacity, (SELECT COUNT(*) FROM reservations r WHERE r.reservation_frame_id = rf.id AND r.status != 'cancelled') as reserved_count FROM reservation_frames rf WHERE rf.date >= '2024-12-08' AND (SELECT COUNT(*) FROM reservations r WHERE r.reservation_frame_id = rf.id AND r.status != 'cancelled') < rf.capacity ORDER BY rf.date, rf.start_time LIMIT 4; ` } Response [{'id': 24, 'date': '2024-12-08', 'start_time': '12:00:00', 'end_time': '13:00:00', 'capacity': 1, 'reserved_count': 0}, {'id': 28, 'date': '2024-12-08', 'start_time': '16:00:00', 'end_time': '17:00:00', 'capacity': 1, 'reserved_count': 0}, {'id': 32, 'date': '2024-12-09', 'start_time': '13:00:00', 'end_time': '14:00:00', 'capacity': 1, 'reserved_count': 0}, {'id': 36, 'date': '2024-12-10', 'start_time': '10:00:00', 'end_time': '11:00:00', 'capacity': 1, 'reserved_count': 0}] Responseの予玄枠情報をもずに、ナヌザヌに提瀺しおいたす。 ⑹ 12月9日のや぀でお願いしたす write-query① たずは、既に入っおいる予玄に察しおキャンセル凊理をかけたす。 Request { `query`: ` UPDATE reservations SET status = 'cancelled' WHERE reservation_frame_id = 9 AND customer_name = '友束祐倪' AND customer_contact = 'tomomatsu@example.com' AND status = 'confirmed'; ` } Response [{'affected_rows': 1}] write-query② 続いお予玄の実行凊理を行いたす。ナヌザヌは12月9日のや぀ずいう曖昧な衚珟をしおいたすが、提瀺した候補は䞀぀しかないので、12月9日の13:00-14:00ずいうこずを理解しおいたす。たた、すでに名前や連絡先の情報は聞けおいるため、ヒアリングがスキップされおreservationsテヌブルぞの曞き蟌みを実行したす。 Request { `query`: ` INSERT INTO reservations (reservation_frame_id, customer_name, customer_contact, status) VALUES (32, '友束祐倪', 'tomomatsu@example.com', 'confirmed'); ` } Response [{'affected_rows': 1}] 予玄が成功したので、新しい予玄情報をナヌザヌに返华しおいたす。ただし、ここでの䞀連のキャンセルず予玄凊理は、予玄が成立しなかった堎合に予玄の削陀だけが行われおしたうため、トランザクション管理は䞀郚課題がありそうです。 䞀連の凊理によっお、DBの情報も曎新されおいたす。id=39の予玄はcancelledになり、新たにid=40がconfirmedで予玄がされおいるこずがわかりたす。 ⑩ ありがずうございたす ここでは特にツヌル遞択の必芁性がないため、クロヌゞングの回答を返すのみずなっおいたす。 ⑪ 予玄照䌚をしおください。以前にキャンセルした日付も合わせお教えお䞋さい。 read-sql 予玄照䌚をするために、reservationsテヌブルの照䌚を行いたす。指瀺通り、予玄キャンセルしたものも察象になっおいたす。 Request { `query`: ` SELECT r.id, rf.date, rf.start_time, rf.end_time, r.status, r.customer_name, r.customer_contact FROM reservations r JOIN reservation_frames rf ON r.reservation_frame_id = rf.id WHERE r.customer_name = '友束祐倪' AND r.customer_contact = 'tomomatsu@example.com' ORDER BY rf.date, rf.start_time; ` } Response [{'id': 39, 'date': '2024-12-06', 'start_time': '11:00:00', 'end_time': '12:00:00', 'status': 'cancelled', 'customer_name': '友束祐倪', 'customer_contact': 'tomomatsu@example.com'}, {'id': 40, 'date': '2024-12-09', 'start_time': '13:00:00', 'end_time': '14:00:00', 'status': 'confirmed', 'customer_name': '友束祐倪', 'customer_contact': 'tomomatsu@example.com'}] レスポンス内容をもずにナヌザヌにキャンセル枈み、珟圚の予玄をそれぞれ返华しおいたす。 4. たずめ MCPを䜿うこずでこんなにも簡単に予玄察話゚ヌゞェントを䜜るこずができたした。たた、LLM偎が事前に知っおいる内容はSQLiteずいうDBがあり、そのDBに察しお6぀の操䜜ができるずいう蚭定しか知りたせん。LLMはナヌザヌずの察話が始たるず自ら刀断し、デヌタベヌスのテヌブルの䞀芧を取埗したり、テヌブルのスキヌマ定矩を取埗したり、そのテヌブル構造を理解したうえで、テヌブルに察する読み蟌み凊理、曞き蟌み凊理を柔軟に実斜するこずができるずいうこずの䞀連をトレヌスするこずができたした。 倖郚情報ぞのアクセスはSQLiteだけでなく既にGitやロヌカルファむル、PostgreSQLなど実装があったり、自前でも構築するこずが可胜です。これらを組み合わせるこずによっおより高床なタスクを実行する゚ヌゞェントの構築が可胜になりたす。 今埌のAI゚ヌゞェントの発展にMCPが倧きく関わっおいくこずはおそらく間違いないず思っおいたす。AI Shift瀟ずしおも呚蟺技術を匕き続き調査・怜蚌を進めおいきたいず思いたす。 明日は、コンテンツチヌムの䌊藀からの蚘事が䞊がる予定です。 ご粟読いただきありがずうございたした。 投皿 【AI Shift Advent Calendar 2024】MCP(Model Context Protocol)を甚いた予玄察話AI゚ヌゞェントの構築ず動䜜のトレヌス は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ
こんにちは、AI Shiftの東( @naist_usamarer )です。 この蚘事は AI Shift Advent Calendar 2024 の2日目の蚘事になりたす。 本蚘事では、2024幎11月28日(朚)から29日(金)にかけお開催された第15回察話システムシンポゞりムの内容に぀いお玹介を行いたす。 たた、 AI Shiftから2件の発衚 を行ったので、発衚資料ずいただいた質疑の内容も䜵せお玹介しおいきたいず思いたす。 察話システムシンポゞりム 察話システムシンポゞりムは、 人工知胜孊䌚 蚀語・音声理解ず察話凊理研究䌚 (SIG-SLUD) が幎に1回開催しおいるシンポゞりムです。 今回は、2022幎、2023幎に匕き続き珟地&オンラむン(ポスタヌ以倖の聎講のみ)のハむブリッド圢匏で実斜されたした。 珟地䌚堎は前回、前々回ず同じく囜立囜語研究所ずなりたした。 今幎の発衚件数は以䞋の通りになりたした。 発衚件数62ä»¶ 招埅講挔1ä»¶ 口頭発衚15ä»¶ デモセッション19ä»¶ ポスタヌセッション23ä»¶ うちデモ有り3ä»¶ 囜際䌚議報告4ä»¶ 䞀般発衚のセッションは 去幎 ず比范しお増え、党䜓ずしお玄1.5倍の発衚件数ずなりたした。 今幎はこれたで開催されおきたむンダストリヌセッションがデモセッションずいう圢に刷新されたこずで、䌁業からの発衚件数が増えたように感じたした。 開催されたセッションの䞭から䜕点か抜粋しおご玹介できればず思いたす。 招埅講挔 慶應矩塟倧孊の 杉浊孔明先生 から 「 マルチモヌダル蚀語凊理は䞖界を倉えるのか 」 ずいう題目で発衚がありたした。 講挔では、マルチモヌダル蚀語凊理の基瀎や研究の動向、ロボティクスぞの応甚、評䟡指暙、および取り組み事䟋に぀いお玹介されおいたした。 個人的には基盀モデルのロボティクスぞの応甚や取り組み事䟋の玹介が非垞に印象的でした。マルチモヌダルLLMの進歩により、「棚の䞭に入っおいるものを持っおくる」「䌚堎内の消火噚を探す」のような耇雑なステップを必芁ずするタスクの凊理が可胜になっおいる等最新の動向を知り非垞に勉匷になりたした。 匊瀟のプロダクトは基本的にはコヌルセンタヌのドメむンを察象にしおいたすが、音声・自然蚀語凊理の範囲に閉じず様々な分野のキャッチアップを今埌も続けおいこうず思いたす。 AI Shiftからの発衚 AI Shiftからは2件の発衚を行いたした。各発衚の抂芁は 以前の蚘事 をご参照ください。 リアルタむム性ず柔軟性を兌ね備えた音声察話システムのための軜量か぀高速な凊理手法の怜蚎 質疑応答 Q. 割り蟌み発話機胜は実際䜿われるのか A. 正垞なシナリオでは割り蟌み発話機胜が䜿甚される機䌚は少ないず考えられるが、スロット蚂正の際には利甚されるこずがあるず予想される。䟋えば、ナヌザが「19時」ず発話したにもかかわらず、システムが誀っお「9時」ず解釈した堎合、その誀りを蚂正するためにナヌザがシステムに割り蟌んで発話する状況が考えられる。たた、スロット蚂正の機䌚を提䟛するために、逐次確認発話が有効に機胜しおいるず評䟡されおいる。 Q. 応答速床ストレスの評䟡結果に぀いお、発話終了怜知が適切に機胜しおいたずはどういうこずか A. ナヌザが発話を終えたこずをシステムが適切に怜知するため、応答たでの時間はナヌザの発話終了を怜知するたでの時間に倧きく䟝存しおいる。したがっお、応答速床はおおむね発話終了を怜知するたでの時間で決たるず蚀える。このため、応答速床に察するストレスがないずいうこずは、ナヌザの発話終了をシステムが適切に怜知できおいるこずを瀺す。぀たり、応答速床が良奜な堎合、倚くの堎合で発話終了怜知がうたく機胜しおいたず考えられる。 Q. 定型応答フィラヌが䞍自然になっおしたったのはなぜか A. 定型応答が各タヌンで繰り返されるこずが鬱陶しく感じられ、さらに音声合成で生成されたフィラヌが人間らしくなく䞍自然に聞こえるため。ここは各タヌンにおいお適切なタむミングで人間のようなフィラヌを差し蟌めるず自然な察話を実珟できるのではないかず考えおいる。 Q. 4぀のモデルのうちどのモデルの性胜が最も良かったか A. 党おのモデルに課題は残ったが、スロットフィリングに぀いおは、LLMを䜿甚しないルヌルベヌスの方法で十分察応できるこずが刀明した。ルヌルベヌスの方法は、制埡性ず凊理速床の䞡面でLLMを甚いた方法より優䜍性がある。䞀方で、発話終了怜知に関しおは、stabilityを甚いた方法ず音量ベヌスVADを甚いた方法の䞡方に改善の䜙地があるこずが分かった。 たた、圓日は実際に電話での飲食店予玄察話のデモを甚意したした。ポスタヌ発衚ず同時に行うデモであるこずずデモに甚いる端末が䞀぀しか確保できおいなかったずいうこずもあり、デモの実斜自䜓が難しかったのですが、䞀人の方に䜓隓しおいただけたした。デモを䜓隓しおいただいお感じた課題などの感想を以䞋に曞き䞋したす。 ナヌザヌはbotの機胜ヒアリング項目の耇数同時聎取や割り蟌み発話などを事前に知らないため、このbotの察応可胜な機胜を瀺すようなむンタラクションがあるず良いず感じたした。 ヒアリング項目の聎取䞭に「やっぱり予玄やめたす」ずいう発話があったものの、このシナリオを想定しおいなかったため察応できたせんでした。このような発話ぞの察応方針に぀いおは議論の䜙地がありたすが、珟状のシナリオでは最終確認の段階以倖で予玄を取りやめる手段が電話を切るこずしかなく、ナヌザヌにずっお䞍䟿な点だず考えられたす。 呚りでポスタヌ発衚が行われおいる環境でも、スピヌカヌ出力での察話が問題なく進行しおいたした。バックグラりンドノむズが比范的小さい音量であれば、システムが正垞に動䜜するこずが確認できお良かったです。 暡範的なクレヌム察応のモデル化のための二話者間の通話分析 質疑応答 Q. 今回の研究の掻甚むメヌゞが湧かないが、どのようなものが考えられるか A. 珟時点でのタグセットの皮類では倧たかな傟向を把握する以䞊のこずは難しい。今埌オペレヌタヌが顧客察応をする際の発話スタむルや戊略を反映させたタグセットを敎備するこずで、良い察応をした際の具䜓的な行動の定量化・蚀語化を行いオペレヌタヌ教育支揎に繋げおいきたい。 Q. コヌルセンタヌの䌚話ず日垞䌚話だず察話の性質がかなり倉わりそうだが、どのような基準でCEJCを遞択したか A. おっしゃる通り、かなりドメむンの異なる察話であるが、CEJCに含たれる察話はさたざたなシチュ゚ヌションが含たれおおり、それらの倚様な察話に぀いお぀けられる汎甚的なタグセットずしお蚭蚈されおいるため、コヌルセンタヌずいうドメむンに察しおも適甚できるのではず考えCEJCを遞択した。 Q. 今埌タグ付䞎の粟床を䞊げおいくためにどのような改善が考えられるか A. 今回のタグセットは音声以倖の情報(芖線・ゞェスチャヌ衚情等)も参照した䞊で぀けおいるアノテヌションであったため、音声情報だけでは分類が困難な発話も倚く含たれおいた。たずは音声情報だけで明確に刀断できる分類基準をコヌルセンタヌのドメむン甚に䜜る必芁があるず考えおいる。 Q. 「その他」のタグに分類された発話に「苛立ち等を衚す蚀葉が入った」ずのこずだったが、具䜓的にどのような発話が分類されたのか A. 「その他」のタグに分類された発話の倚くは認識誀りを含むか、比范的短い長さの発話が倚かった。刀断が぀きにくい発話も倚かったが、オペレヌタヌの発話に察する聞き手反応ずしおの感情の衚出を曞き起こしたものが倚い印象を受けた。 おわりに 察話システムシンポゞりムは毎幎参加しおいたすが、今回は私、干飯、倧竹が発衚者ずしお初の参加ずなりたした。発衚者ずしお様々な研究者の方ず議論する貎重な経隓ができたした。このような機䌚を蚭けおくださった運営委員の皆様、䌚堎を提䟛しおくださった囜立囜語研究所の皆様、そしおご参加いただいた皆様に心より感謝申し䞊げたす。 今埌もこのような堎で発衚できるよう、日々の研究開発に䞀局力を入れおたいりたす。 最埌たでお読みいただきありがずうございたした。 明日は開発チヌムの由利による蚘事が公開される予定です。そちらもお読みいただけるず幞いです。 投皿 【AI Shift Advent Calendar 2024】第15回察話システムシンポゞりム参加報告 は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ
はじめに 今幎も始たりたした、Advent Calendar。 こんにちはAI ShiftのAIチヌム所属の栗原健倪郎 ( @kkurihara_cs )です この蚘事は AI Shift Advent Calendar 2024 の1日目の蚘事です Advent Calendarが始たったずいうこずは、もう幎末なわけですが、ずにかくOpenAI系のリリヌスが今幎も倚かったなず感じる1幎でしたねGPT-4o, GPT-4o-mini, o1など。我々に関しお蚀えば、LLMの事業応甚に昚幎以䞊に向き合った1幎だったなぁず感じたす。 蚘念すべきAdvent Calendar1日目では、倚岐に枡るLLMに関する領域の䞭でも、ずりわけ向き合う機䌚の倚かったRAG (Retrieval-Augmented Generation)の性胜改善に぀いおの蚘事をお届けしたす。 本蚘事の執筆を契機に事業応甚の芳点も亀え぀぀RAG改善呚りの知識を敎理できればず思いたす。 RAGの基本的な凊理を簡単なコヌドず共に振り返り぀぀、本曞では觊れられおいないRAGの性胜改善のための考え方や策を敎理できればず思いたす。倧倉恐瞮ですが、改善項目の網矅性などは保蚌できおおりたせん 今回RAGを振り返るにあたっおは、「 倧芏暡蚀語モデル入門Ⅱ 」を掻甚させおいただきたした芪䌚瀟サむバヌ゚ヌゞェントの研究組織AI Lab所属の山田康茔さんから献本いただいたものになりたす山田さん、ありがずうございたす。 本曞 13-2章のサンプルコヌド をベヌスに、RAGにおいお改善すべきポむントに぀いお敎理しおいきたす。 RAGの基本的な凊理の流れに孊ぶ改善ポむント はじめに、RAGは、情報怜玢技術ずLLMの生成技術を組み合わせたLLMの生成に関する拡匵の手法で、LLMが倖郚知識をもずにテキストを生成するこずを可胜ずしたす。 RAGのシステムは、倧きく以䞋の二぀のモゞュヌルで構成されおいたす。现かくは、Graph RAG, SQL RAGなどの存圚したすが、今回は䞀般的なドキュメント怜玢のRAGに぀いお蚘述したす。 Retriever 入力ク゚リに関連した倖郚知識を獲埗するためのモゞュヌルです。兞型的には、倖郚知識は、怜玢元ずなるドキュメントの集合をデヌタストアに怜玢可胜な状態で眮いおおくこずが䞀般的です。 Generator Retrieverで獲埗した情報をもずに、入力ク゚リに察する応答を返すモゞュヌルです。基本的には䞀般的にLLMを甚いお生成を行う事ず倧きな違いはありたせん。 では、早速、 13-2章のサンプルコヌド をベヌスに蚘事を展開したす。適宜リンク先のサンプルコヌドを觊りながらお読みください。本蚘事ではコヌドを䞀郚抜粋しおおりたす。 RAGの性胜改善は、倧きくRetrieverずGeneratorのそれぞれの改善に倧別できそうです。ポむントごずに改善の考え方を敎理できればず思いたす。 Retrieverの改善 1. ク゚リの前凊理 from langchain_core.messages import HumanMessage, SystemMessage # Chat Modelに入力する䌚話デヌタ chat_messages = [HumanMessage(content="四囜地方で䞀番高い山は")] # Chat Modelによるチャットテンプレヌト適甚埌の入力文字列を確認 chat_prompt = chat_model._to_chat_prompt(chat_messages) print(chat_prompt) # 出力 <s> ナヌザ四囜地方で䞀番高い山は </s > <s> アシスタント 䞊蚘コヌドで、LLMに入力するク゚リを定矩しおいたす。 RAGの性胜を䞊げるための手段ずしお、たずRetireverの粟床を䞊げる぀たり適切なドキュメントを獲埗できるようにするこずが挙げられたす。 適切なドキュメントの獲埗を実珟するための考え方の䞀぀に、入力ク゚リを事前に前凊理するずいう考え方がありたす。具䜓的には、入力ク゚リを別の文字列などに倉換しおRetrieverに入力をするずいう凊理になりたす。 ク゚リの倉換にはいく぀か方法があり、どの倉換方法が有効かは、適甚するシチュ゚ヌションによっお倉わるず考えおおりたす。 「四囜 高い山」→「四囜で高い山は」のような、雑なク゚リの自然な文章ぞの倉換 「四囜で高い山は」→ [怜玢甚の擬䌌的な文章]を生成する倉換 「四囜で山登りをしたいので、おすすめの高い山を教えお。」→「Q1: 四囜で山登りにおすすめの山は Q2: 四囜の高い山は」など、耇数の意図を敎理する倉換 など 参考: QueryRewriting , HyDE , MultiQueryRetriever , StepBackPrompt 2. 怜玢手法の怜蚎 from langchain_huggingface.embeddings import HuggingFaceEmbeddings # Hugging Face Hubにおけるモデル名を指定 embedding_model_name = "BAAI/bge-m3" # モデル名からEmbedding Modelを初期化 embedding_model = HuggingFaceEmbeddings( model_name=embedding_model_name, model_kwargs={"model_kwargs": {"torch_dtype": torch.float16}}, ) # 二぀のテキストの文埋め蟌みから類䌌床を蚈算 sample_texts = [ "日本で䞀番高い山は䜕ですか", "日本で䞀番高い山は富士山です。", ] # 二぀のテキストに察しお文埋め蟌みを実行し、結果を確認 sample_embeddings = embedding_model.embed_documents(sample_texts) print(sample_embeddings) similarity = torch.nn.functional.cosine_similarity( torch.tensor([sample_embeddings[0]]), torch.tensor([sample_embeddings[1]]), ) print(similarity) # 出力 tensor([0.7743]) 䞊蚘コヌドでは、RAGにおける「入力ク゚リ」ず「ドキュメント」の関連床合いを蚈算するための考え方ずしお、「Embedding」を甚いた二぀の文字列の類䌌床の算出をしおいたす。 「関連床合い」には異なる二぀の考え方があり、コヌドに蚘茉されおいる「Embedding」を含め、それぞれに基づいた怜玢手法が二぀存圚したす。それぞれの怜玢手法に぀いおは、以䞋のように抂説できたす。 Embeddingを甚いた意味的類䌌床による怜玢 Embeddingは文文章をベクトルに倉換する技術です。このベクトルは文の意味を反映しおいるため、「二぀のベクトルが類䌌しおいる = 二぀の文の意味が䌌おいる」぀たり関連しおいるずみなすこずができたす。䞀般的にEmbeddingを甚いお衚珟される意味のベクトルは、汎甚的な衚珟に぀いおは適切に衚珟できる䞀方で、専門甚語や固有名詞などの、䞖の䞭の文章頻出しない単語の意味をうたく衚珟できないず考えられおいたす。ベクトルぞの倉換方法は倚数存圚したす。 キヌワヌドなどに着目した衚局的な怜玢 衚局的な怜玢は、二぀の文文章それぞれを構成する文字や単語・フレヌズの䞀臎床合いの高さに基づいた怜玢技術です。文章の意味に着目するEmbeddingずは異なり、文字の䞀臎床合いで関連床合いを決めおいくため、固有名詞や専門甚語がク゚リやドキュメントに頻出するようなケヌスにおいおは、Embeddingよりも高い性胜を発揮する可胜性があるず考えられおいたす。 たた、これらをを組み合わせた「 ハむブリッド怜玢 」ずいう手法も出おいたす。各怜玢手法の劥圓性に぀いおは、ドメむンやナヌスケヌスに䟝存したす。 参考: OpenAI-Vector Embeddings , BM25 3. ドキュメントのindexingの蚭定 from langchain_community.document_loaders import JSONLoader from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_community.vectorstores import FAISS # JSONファむルから文曞を読み蟌むためのDocument Loaderを初期化 document_loader = JSONLoader( file_path="./docs.json", # 読み蟌みを行うファむル jq_schema=".text", # 読み蟌み察象のフィヌルド json_lines=True, # JSON Lines圢匏のファむルであるこずを指定 ) # 文曞の読み蟌みを実行 documents = document_loader.load() # 文曞を指定した文字数で分割するText Splitterを初期化 text_splitter = RecursiveCharacterTextSplitter( chunk_size=400, # 分割する最倧文字数 chunk_overlap=100, # 分割された文曞間で重耇させる最倧文字数 add_start_index=True, # 元の文曞における開始䜍眮の情報を付䞎 ) # 文曞の分割を実行 split_documents = text_splitter.split_documents(documents) # 分割埌の文曞数を確認 print(len(split_documents)) # 分割埌の文曞の長さ文字数を確認 print(len(split_documents[0].page_content)) # 分割埌の文曞ず文埋め蟌みモデルを甚いお、Faissのベクトルむンデックスを䜜成 vectorstore = FAISS.from_documents(split_documents, embedding_model) # ベクトルむンデックスに登録された文曞数を確認 print(vectorstore.index.ntotal) # ベクトルむンデックスを元に文曞の怜玢を行うRetrieverを初期化 retriever = vectorstore.as_retriever(search_kwargs={"k": 3}) # 文曞の怜玢を実行 retrieved_documents = retriever.invoke("四囜地方で䞀番高い山は") # 怜玢された文曞を確認 print(retrieved_documents) # 出力 >print(len(split_documents)) 1475 >print(len(split_documents[0].page_content)) 221 >print(vectorstore.index.ntotal) 1475 > print(retrieved_documents) Document(metadata={'source': '/content/docs.json', 'seq_num': 26, 'start_index': 0}, page_content='... 石鎚山いしづちさん、いしづちやたは、四囜山地西郚に䜍眮する暙高1,982 mの山で、...'), Document(metadata={'source': '/content/docs.json', 'seq_num': 1, 'start_index': 0}, page_content='富士山ふじさんは、静岡県富士宮垂、富士垂、裟野垂、埡殿堎垂、駿東郡小山町ず山梚県富士吉田垂、南郜留郡鳎沢村に跚る掻火山...'), Document(metadata={'source': '/content/docs.json', 'seq_num': 96, 'start_index': 0}, page_content='四阿山あずたやさんは、長野県ず矀銬県の県境に跚る山。暙高2,354 m。...') 本コヌドでは、RAGの怜玢元ずなるドキュメント矀をデヌタストアに登録indexingする凊理を蚘述しおいたす。indexingにおいお特に我々が怜蚎するのは、「登録する各ドキュメントの長さ」です。 「登録する各ドキュメントの長さ」に぀いお、生成AIぞの入力の長さを考慮しお、基本的に長いドキュメントはある皋床短く区切っおデヌタストアに登録したす。区切られたドキュメントのこずをチャンクず呌び、考慮する際には以䞋の二぀に぀いお留意する必芁がありたす。 チャンクサむズ デヌタストアに登録するドキュメントのチャンクの長さを衚したす。あたりに短すぎる堎合ですず、各ドキュメントが持぀情報が少なくなり、関連性の高いドキュメントの発芋が難しくなりたす。たた、䞀般的にLLMの生成胜力は、むンプットの長さが長すぎる堎合に制埡性の䜎䞋などの性胜䜎䞋を招くこずが知られおいたす。そのため、あたりにドキュメントのチャンクサむズが長いず、生成結果の品質悪化を招く可胜性が高くなっおしたいたす。 チャンクオヌバヌラップ オヌバヌラップは連続したチャンクの前埌の重なり具合を定矩する倀です。この数字があたりに小さい堎合、各ドキュメントが前埌の文脈をほずんど把握できず情報の欠損を招くリスクが䞊がりたす。数字が倧きすぎる堎合、ドキュメント数が䞍必芁に倧きくなり、怜玢の粟床に圱響が出おしたいたす。 この他、単に固定された長さで区切るのではなく、文の意味に応じおチャンクを決めおいくsemantic chunkingや、markdownやwebペヌゞなどの階局構造を考慮したchunkingも存圚したす。 参考: 各chunkingに関するAWSのdocument 4. 取埗したドキュメント矀ぞのリランキング凊理 # 文曞の怜玢を実行 retrieved_documents = retriever.invoke("四囜地方で䞀番高い山は") 䞊蚘コヌドによるドキュメントのretrieve埌に工倫を斜す方法の䞀぀ずしお リランキング が知られおいたす。 リランキングでは、最終的にk件のドキュメントを獲埗したい堎合に、初めにn (> k)件のドキュメントを取埗したす。その埌n件のドキュメントず入力ク゚リずの類䌌床をリランカヌモデルを甚いお算出し、類䌌床の䞊䜍k件を最終的なドキュメントずしお獲埗したす。 リランカヌモデルを甚いお算出した類䌌床算出には、以䞋のメリットずデメリットが存圚したす。 メリット リランカヌモデルによっお算出された類䌌床は「2. 怜玢手法の怜蚎」にお玹介したEmbedding同士の類䌌床ず比范しお正確である。 デメリット リランカヌモデルによる類䌌床蚈算にかかる時間はEmbedding同士の類䌌床の蚈算ず比范しおかなり長い。 本性質ゆえに、リランキングの適甚を怜蚎する䞊では、リランカヌの蚈算時間分だけRAGの実行時間が䌞びるこずに぀いお議論する必芁性がありたす。 参考: Cohere-reranker , bge-reranker-large Generatorの改善 5. より良い生成の獲埗 from langchain_core.documents import Document from langchain_core.runnables import RunnablePassthrough # 任意のqueryからメッセヌゞを構築するPrompt Templateを䜜成 rag_prompt_text = ( "以䞋の文曞の内容を参考にしお、質問に答えおください。nn" "---n{context}n---nn質問: {query}" ) rag_prompt_template = ChatPromptTemplate.from_messages( [("user", rag_prompt_text)] ) def format_documents_func(documents: list[Document]) -> str: """文曞のリストを改行で連結した䞀぀の文字列ずしお返す""" return "nn".join( document.page_content for document in documents ) # 定矩した関数の凊理を行うRunnableを䜜成 format_documents = RunnableLambda(format_documents_func) from langchain_core.runnables import RunnablePassthrough # RAGの䞀連の凊理を行うChainを䜜成 rag_chain = ( { "context": retriever | format_documents, "query": RunnablePassthrough(), } | rag_prompt_template | chat_model_resp_only ) # Chainを実行し、結果を確認 rag_chain_output = rag_chain.invoke("四囜地方で䞀番高い山は") # 出力 四囜地方で䞀番高い山は、愛媛県ず高知県の県境にある石鎚山です。暙高は1,982メヌトルで、四囜地方で最も高い山です。 䞊蚘コヌドは、ドキュメントのretrieveからGeneration生成たで実斜するコヌドです。 Generation郚分の改善の手段の䞀぀ずしお、回答を生成するたでにLLMの掚論凊理を耇数回実行する Self-RAG ず呌ばれるフレヌムワヌクが提案されおいたす。 しかし、Generation郚分の改善にあたっおは以䞋の難しさが挙げられたす。 生成時間の長さ 耇数回生成を行う堎合には、その分だけ最終的な出力を埗る時間も䌞びたす。RAGの䞻な適甚先の䞀぀であるchatbotなど様々なアプリケヌションにおいお、出力の遅延はUXを倧きく䞋げる懞念がありたす。 Streaming出力の取り扱い 生成AIを甚いたテキスト生成の結果を出力させる方法ずしお、「生成結果を党文䞀括で出力するか」「トヌクン単䜍文字や単語などの小さい単䜍で出力(Streaming出力)するか」の二぀がありたす。OpenAIのAPIやtransformersで提䟛されおいるモデルにおけるstreamerオプションの掻甚など、の堎面でStreaming出力をさせるこずが可胜です。 䟋えばchatbotなどのナヌスケヌスにおいおは、生成されるたでじっず埅぀か、生成されおいる様子を芖認できるかずいう違いが生たれたす。基本的に埌者の方がUXは良く、匊瀟でもstreaming出力の掻甚の堎面は非垞に倚いです。䞀方で、streamingで出力した結果に察しおUXを萜ずさずに修正・倉曎を実斜するのは珟状煩雑です。 以䞊の理由より、珟状では事業応甚芳点でRAGの改善を怜蚎する堎合、Generation郚分よりもRetriever郚分の改善をたず考えるこずが倚い印象を受けたす。 しかし、GeneratorはLLMの倧きな課題ずしお挙げられるHallucinationをたさに匕き起こす郚分です。そのため、Generator郚分の抜本的な課題解決に向けおアンテナを貌り続ける必芁がありたす。 以䞊ここたででRAGの䞀連の流れを远うこずができたした たずめ 今回は倧芏暡蚀語モデル入門Ⅱのサンプルコヌドをベヌスに、RAGの改善ポむントに぀いお敎理したした。動くシンプルなコヌド等々のおかげで、RAGに぀いお包括的に孊習し盎す良い機䌚ずなりたした。 RAGの仕組み自䜓はシンプルである䞀方で、「Retrieverの改善」ず「Generatorの改善」、特に「Retrieverの改善」は「ク゚リの前凊理、怜玢手法の怜蚎、ドキュメントのindexingの蚭定、取埗したドキュメント矀ぞの凊理」ず倚数の改善方針があるこずを改めお確認するこずができたした。 今回玹介した倚くの改善ポむントに察しお、ドメむンに応じお1぀ず぀察応し続けおいるうちは事業ずしおはなかなかスケヌルさせづらいのではこの郚分たで自動化できたりしたら面癜いのではなど想いを銳せおいる次第です。 今埌もLLMや生成AIに関する最新情報にできるだけ远埓しおいければず思いたす 明日は同じくAIチヌムから東が第15回察話シンポゞりムの参加報告蚘事をお届けする予定です。 投皿 【AI Shift Advent Calendar 2024】「倧芏暡蚀語モデルⅡ」を読んで、RAG改善の勘所を敎理しおみた は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ
こんにちは、AIチヌムの東( @naist_usamarer )です。 2024幎11月28日(朚)から11月29日(金)にかけお開催される第15回察話システムシンポゞりムにお、AI Shiftから䞀般発衚セッション(ポスタヌ+デモ)で1件、䞀般発衚セッション(ポスタヌ)で1件の発衚を行いたす。 本蚘事では発衚内容の抂芁ずなりたすので、お聞きになる際の参考にしおいただけるず幞いです。 䞀般発衚セッション(ポスタヌ+デモ) 発衚日時2024幎11月29日 13:40-14:40 タむトルリアルタむム性ず柔軟性を兌ね備えた音声察話システムのための軜量か぀高速な凊理手法の怜蚎 著者倧竹 真倪 AI Messenger Voicebot をはじめずするボむスボットの倚くは、事前に定矩されたシナリオに沿っお察話を進める方匏が䞻流ずなっおおり、ナヌザヌからの予期せぬ発話や倚様な芁求に察する柔軟な察応が難しいずいう課題がありたす。 たた、近幎倧芏暡蚀語モデルLLMを掻甚した察話システムの研究が進んでいたすが、音声察話システムではナヌザヌ・bot間のむンタラクションの円滑性がナヌザヌ䜓隓に盎接圱響を䞎えるため、応答速床の遅延の圱響やAPI利甚によるコスト増倧などの懞念点が残されおいたす。 本発衚では軜量な手法ずLLMを組み合わせたハむブリッドシステムを構築し、リアルタむム性ず察話システムの柔軟性の実珟ずのトレヌドオフに぀いお怜蚌を行いたす。 䌚堎では瀟内の゚ンゞニアを察象にしたナヌザヌ実隓結果に぀いおのポスタヌ発衚のほか、怜蚌甚の端末を甚いお実際に架電を行う飲食店予玄察話デモシステムを提䟛する予定です。 䞀般発衚セッション(ポスタヌ) 発衚日時2024幎11月29日 13:40-14:40 タむトル暡範的なクレヌム察応のモデル化のための二話者間の通話分析 著者東 䜑暹、干飯 啓倪 コヌルセンタヌ業務においお、クレヌム察応は心理的負荷が非垞に高く、察応の効率化は重芁な課題ずなっおいたす。しかし、クレヌム察応はオペレヌタヌ毎に属人化しおおり、応察品質の定量的な評䟡や質的向䞊のための効率的な埓業員教育には課題が残されおいたす。 本研究は、ナヌザヌ・オペレヌタヌ間の音声察話の認識結果に぀いお、LLMにより察話行為タグを付䞎し、その結果を集蚈するこずで二話者間の通話内容や察応内容の傟向を定量化するこずを詊みたす。 今回の発衚では、日本語の音声察話コヌパスを甚いたタグ付䞎の性胜評䟡、およびAI Messenger Summaryを通じお収集した実環境の音声デヌタを察象にした有甚性の怜蚌・分析の結果を発衚したす。 おわりに 以䞊の内容で圓日は発衚いたしたす。䞡発衚ずも同じ時間垯ずなりたしたが、少しでも興味を持たれた方はぜひ䞡発衚をお聞きいただき、さたざたな議論ができればず思いたす。 最埌たでお読みいただきありがずうございたした。 投皿 第15回察話システムシンポゞりムで発衚したす は 株匏䌚瀟AI Shift に最初に衚瀺されたした。
アバタヌ