こんにちは、Algomaticのnaotoota(@OTA57)です。現在はChief of Staffとして横断的にさまざまなカンパニーの支援を実施しています。 LLM STUDIOにおいてはPOの役割を担っているのですが、今日はLLM STUDIOのチーム運営における生成AIを活用したちょっとした取り組みをご紹介します。
LLM STUDIOではリモートのメンバーもいるため、メンバーが毎日の勤怠ややること、相談事項等をSlackにて毎日投稿(dailyスレッドと呼んでいます)しているのですが、 そこに生成AIを絡めてちょっとした楽しみを加えてみたという事例です。
【この記事に書いてあること】
- 「今日の一言のお題」自動生成開発の経緯
- 生成AIの得意、不得意について
- 「今日の一言のお題」自動生成の具体的な仕組み
- 生成AIの使い所を見極めて、業務に組み込むことの重要性
【この記事の想定読者】
- 生成AIを業務に活用したいと考えているエンジニアの方
- LLMの特性について興味がある方
「今日の一言のお題」自動生成開発の経緯
元々dailyスレッドはSlackのワークフローを用いて毎日自動投稿されるスレッドでした。
今日の一言はメンバーの会話のきっかけを作るべく置かれた項目なのですが、毎日欠かさずそれぞれがネタを考えて投稿するのは案外大変です。 コミュニティメンバーが食いつきそうな話題を選んだり、場の雰囲気を壊さないような書き方をしたりと、意外と神経を使う必要がありました。 しかも、毎日となると、ネタ切れを起こさないようにストックしておく必要もあります。
そこで「毎日続けるタスクこそ自動化するに限る」ということで、お題の自動生成に着手しました。
ただ、お題を考えてくださいとChatGPTにお願いするのだと同じようなお題が続いたり幅が出ないので、「今日は何の日」かを加味した上でお題を考えてもらうようにしました。 元々人力でやっていた時に「今日は何の日」かを加味してお題を決定していたことがあったのを見て真似した形です。
この実装自体は難しいことは何もないのですが、生成AIを活用する上で大事な特性をよく理解した上での使い所を見極めのいい例でした。
実際のアウトプット例はこちらです。
生成AIの得意・不得意
「今日の一言のお題」の自動生成を実装する中で、改めて生成AIの得意・不得意を実感しました。
得意1 アイディア出し
生成AIは「アイデア出し」が非常に得意です。dailyスレッドでは、「今日の一言のお題」を毎回考える必要がありますが、これをLLMに投げると、ユニークで適度にユーモアのある話題を次々と提案してくれます。
人間だと毎日飽きずにアイデアを出し続けるのは至難の業ですが、AIならいくらでも発想してくれる。これは生成AIの特性を存分に活かせる場面だと感じました。
得意2 人間の代弁
生成AIは「人間が言いづらいこと」を代弁するのも得意だと思います。
例えば、コミュニティ運営の中では、「このようなルールを守りましょう」といった注意喚起のメッセージを出す必要もあります。 しかし、強すぎると場の雰囲気が壊れるし、かといって優しすぎても伝わらない。そんな絶妙な言い回しをLLMに探ってもらうのは結構便利だったりします。 機械が言うことで、人間関係に気を遣わずにすむというメリットもありますしね。
実際に人力でのお題設定ではお題にならなさそうな内容がお題になることもあります。
また実際にこのお題でのメンバーの今日の一言は以下のようなものがあり、チームの会話が発生するきっかけとなっています。
不得意1 ハルシネーション
生成AIにはハルシネーションという弱点もあります。 今回、「今日は何の日」の情報をLLMに全面的に任せると、実在しない記念日を捏造したりすることがわかりました。 日付に関する知識は学習データの更新頻度と密接に関係するので、そこまで正確でない可能性は予想していましたが、思った以上にデタラメなことを言うんですよね。 結局、この部分はロジックでスクレイピングして実装するのがベターでした。
ここまでの経験から言えるのは、生成AIの特性を十分理解した上で活用することが何より大切だということです。 得意分野は思い切って任せつつ、苦手な部分は別の手段で補う。 そんな使い分けが、生成AIを業務に効果的に組み込む鍵になると感じています。
「今日の一言のお題」自動生成の具体的な仕組み
実際の「今日の一言のお題」自動生成機能は、AIの特性を踏まえた作りになっています。
まず、「今日は何の日」の部分は、外部のWebサイトから情報を取得するロジックを組みました。 具体的には、毎日が記念日というサイトをスクレイピングして、その日の記念日を抽出する仕組みです。 正直、LLMでもある程度の記念日は生成できるのですが、きちんと実在するものを選り分けるのが難しいんですよね。 そこは素直にプログラミングで実装した方が確実だろうという判断です。
一方、「今日の一言のお題」の部分は、まさにLLMの出番です。 ここでは、その日の記念日に関連したお題をLLMに生成してもらっています。 今日の記念日が「ビスケットの日」だったら、「あなたの好きなビスケットについて語ってください」といった具合ですね。 このアイデア出しこそ、LLMの創造力が遺憾なく発揮できる場面だと思います。
AWS Lambdaで定期実行しており、実際のコードはこんな感じです。
from datetime import datetime from lxml import html import random import requests from openai import OpenAI from slack_sdk.webhook import WebhookClient API_KEY = "" WEBHOOK_URL = "" BASE_URL = "https://www.nnh.to/" MODEL = "gpt-3.5-turbo" TODAY = datetime.now().date() def send_slack_message(url, text): webhook = WebhookClient(url) webhook.send(text=text) def fetch_theme_from_openai(prompt): client = OpenAI(api_key=API_KEY) messages = [{"role": "user", "content": prompt}] response = client.chat.completions.create(model=MODEL, temperature=0.0, messages=messages) return response.choices[0].message.content def get_today_related_content(today): day_url = f"{BASE_URL}{today.strftime('%m')}/{today.strftime('%d')}.html" response = requests.get(day_url) doc = html.fromstring(response.content) contents = {} for node in random.sample(doc.xpath('//h4[@class="ordinary"]'), 2): texts = traverse_and_accumulate_texts(node, []) contents[node.text_content()] = "\n".join(texts) return contents def traverse_and_accumulate_texts(node, texts): while node.getnext() is not None and node.getnext().tag == "p": node = node.getnext() texts.append(node.text_content()) return texts def format_contents(contents): return "\n\n".join([f"*{k}*\n{v}" for k, v in contents.items()]) def get_todays_prompt(contents_text): return f""" チームの朝会で一人一人が発表をするのですが、その際に今日の一言を発してもらいます。 毎日違うテーマで各メンバーに発表して欲しく、そのためのお題を考えて欲しいです。 ちなみに、今日はこんな日です。 {contents_text} お題は上記の今日にまつわる内容が好ましく、一つだけ考えてください。 """ def create_slack_post(today, contents_text, theme): return f"""【{today.strftime("%m/%d(%a)")}のおはようスレ】 みんなおはよう〜〜〜 LLM STUDIOで今日稼働するみんな、稼働開始する前にNotionに記入をしてね! {get_notion_link()} *↓今日はこんな日↓* {contents_text} *今日の一言のお題!(powered by GPT-3.5)* {theme}""" def lambda_handler(event, context): contents = get_today_related_content(TODAY) formatted_contents = format_contents(contents) daily_prompt = get_todays_prompt(formatted_contents) theme = fetch_theme_from_openai(daily_prompt) post_text = create_slack_post(TODAY, formatted_contents, theme) send_slack_message(WEBHOOK_URL, post_text)
こうして、dailyスレッドの内容は、外部データに基づくロジック処理と、LLMによる自然言語生成を組み合わせて作られています。 ロジックの部分はプログラミングに詳しいエンジニアでないと対応できませんが、いったん作ってしまえば安定して動いてくれるのがいいですね。 他方、LLMへの指示出しは、プロンプトエンジニアリングのスキルが問われますが、プログラミングほどの専門性は要りません。 つまり、日々のメンテナンスは、プロンプトを工夫するだけで、エンジニア以外のメンバーでも対応できるわけです。
このように、dailyスレッド自動投稿は、生成AIとロジックの組み合わせによって成り立っています。 LLMには得意な部分を担当してもらいつつ、苦手な部分は別の手段で補完する。 まさに、生成AIの使い所を的確に判断した好例だと思います。
終わりに 生成AIの使い所を見極めて業務に組み込もう!
ここまでdailyスレッド自動投稿の開発経緯と、その過程で得られた生成AIの知見について述べてきました。 改めて振り返ると、LLMを業務に活用する上で最も大切なのは、その特性を見極め、適材適所で用いることだと実感しています。
LLMは確かに万能ではありません。知識の正確性が問われる場面では、ハルシネーションのリスクを考慮せねばなりません。 しかし、アイデア出しや言葉のニュアンス調整など、人間の創造性を拡張する用途では、大いに威力を発揮してくれます。 要は、LLMに何を期待するのか、そしてどこまで任せるのかを適切に見定めることが大切です。
また、LLMを活用すると決めたからには、プロンプトエンジニアリングのスキルを磨くことも欠かせません。 素人考えの質問では、LLMの能力を引き出せません。 どんな指示を与えれば望む結果が得られるのか、trial and errorを繰り返しながら、コツをつかんでいく必要があります。
かといって、最初から完璧を求める必要はありません。 まずは、LLMに任せられる部分を少しずつ増やしていく。 そうした段階的なアプローチこそが、生成AIを業務に円滑に導入する近道だと思うのです。
dailyスレッド自動投稿の開発は、まさにこの段階的アプローチを実践した試みでした。 当初は手作業で行っていたタスクを、徐々に自動化の範囲を広げていく。 その過程で、LLMの特性を見極め、使い所を的確に判断する。 こうした地道な取り組みの積み重ねが、ゆくゆくは業務全体の効率化につながるはずです。
今後も、AlgomaticではLLMを積極的に活用しつつ、よりよいサービス開発に邁進していきたいと思います。 この記事が、皆さまのLLM活用の一助となれば幸いです。
生成AI時代を代表する会社を一緒に作りませんか
最後に会社の宣伝になるのですが、2023年4月の創業から、まだまだ僕らは、創業期です。共に生成AI時代を代表する会社を創る「創業メンバー」を募集しています。
興味を持っていただいた方、まずは気軽に、お話しさせてください!
大田とのカジュアル面談はこちら
その他採用に関する情報はこちらをご覧ください。