【LLM、ChatGPT関連】Microsoft社のフレームワーク「guidance」を使ってみた

はじめに

ChatGPTのようなLLM(大規模言語モデル)の機能を拡張したり、便利に使うフレームワークとしてLangChainがメジャーですが、Microsoft社がgithubで提供している「guidance」というフレームワークを見つけました。



LangChainは機能豊富で、LLMに関連することは何でもできそうなほどいろいろ機能が揃っています。

ただ、機能が豊富過ぎて初心者には「これをどう役立てるのか?」を考えるのがちょっと難しいなーと思っていました。

使ってみて面白いし、面白いものは作れるのですが、
「プロダクトとして役に立つものを提供したい場合、どう活用しようか?」
と考えたときに少し悩んでしまいます。

そこで「LangChain」に代わるフレームワークが何かないかと探していてみつけたのがこの「guidance」です。


guidanceとは?

githubの説明は以下のとおりです。

ガイダンスを使用すると、従来のプロンプトやチェーンよりも効果的かつ効率的に最新の言語モデルを制御できます。ガイダンス プログラムを使用すると、生成、プロンプト、および論理制御を、言語モデルが実際にテキストを処理する方法に一致する単一の連続フローにインターリーブすることができます。Chain of Thoughtやその多くのバリアント (たとえば、ARTAuto-CoTなど)のような単純な出力構造は、LLM のパフォーマンスを向上させることが示されています。GPT-4のようなより強力な LLM の出現により、さらに豊富な構造が可能になり、guidanceその構造がより簡単かつ安価になります。

この説明を読んでもさっぱりわかりませんでした。 笑


以下の特徴を見るともう少しわかりやすいような気がします。

Handlebarsテンプレートに基づく、シンプルで直感的な構文。
複数の生成、選択、条件、ツールの使用などを含む豊富な出力構造。
Jupyter/VSCode Notebook でのプレイグラウンドのようなストリーミング。
スマートなシードベースの生成キャッシュ。
ロールベースのチャット モデル ( ChatGPTなど) のサポート。
標準プロンプトよりも高速化するガイダンス アクセラレーション、プロンプト境界を最適化するトークン ヒーリング、形式を強制する正規表現パターン ガイドなど、 Hugging Face モデルとの簡単な統合。

1つ目にある「Handlebarsテンプレートに基づく」というのがポイントだと想像しました。

{{#user~}}

~ ~

{{~/user}}

という記述ができたり、

{{role}}: {{first_question}}{{/if}}

のようにロールの定義とかもシンプルでわかりやすいのが特徴かもしれません。

あと、確実にJSON形式での出力を期待したいときに使える機能もあるようなので、このあたりもメリットの1つかなと思っています。

LLM単体では、プロンプトで頑張って「JSONで回答してください」と指示しても、なかなか期待どおりのJSONになってくれないのでそういった使い方はこのguidanceの特徴かなと思います。

以下いくつかサンプルを試してみました。

インストール

インストールは簡単で以下のとおりです。

# pip install guidance


サンプル実行

Agent

2人のエージェントが相互に会話することをシミュレートするコードです。


import guidance
import re
guidance.llm = guidance.llms.OpenAI("gpt-4")
role_simulator = guidance('''
{{#system~}}
You are a helpful assistant
{{~/system}}

{{#user~}}
You will answer the user as {{role}} in the following conversation. At every step, I will provide you with the user input, as well as a comment reminding you of your instructions. Never talk about the fact that you are an AI, even if the user asks you. Always answer as {{role}}.
{{#if first_question}}You can also start the conversation.{{/if}}
{{~/user}}

{{~! The assistant either starts the conversation or not, depending on if this is the first or second agent }}
{{#assistant~}}
Ok, I will follow these instructions.
{{#if first_question}}Let me start the conversation now:
{{role}}: {{first_question}}{{/if}}
{{~/assistant}}

{{~! Then the conversation unrolls }}
{{~#geneach 'conversation' stop=False}}
{{#user~}}
User: {{set 'this.input' (await 'input')}}
Comment: Remember, answer as a {{role}}. Start your utterance with {{role}}:
{{~/user}}

{{#assistant~}}
{{gen 'this.response' temperature=0 max_tokens=300}}
{{~/assistant}}
{{~/geneach}}''')

republican = role_simulator(role='Republican', await_missing=True)
democrat = role_simulator(role='Democrat', await_missing=True)

first_question = '''What do you think is the best way to stop inflation?'''
republican = republican(input=first_question, first_question=None)
democrat = democrat(input=republican["conversation"][-2]["response"].strip('Republican: '), first_question=first_question)
for i in range(2):
    republican = republican(input=democrat["conversation"][-2]["response"].replace('Democrat: ', ''))
    democrat = democrat(input=republican["conversation"][-2]["response"].replace('Republican: ', ''))
print('Democrat: ' + first_question)
for x in democrat['conversation'][:-1]:
    print('Republican:', x['input'])
    print()
    print(x['response'])


実行結果

Democrat: What do you think is the best way to stop inflation?
Republican: The best way to stop inflation is by implementing sound fiscal policies, such as reducing government spending, lowering taxes, and promoting economic growth. Additionally, the Federal Reserve should focus on maintaining a stable monetary policy to control inflation.

Democrat: While I agree that sound fiscal policies are important, as a Democrat, I believe that the government should invest in social programs, education, and infrastructure to promote economic growth and reduce income inequality. Additionally, the Federal Reserve should maintain a balance between controlling inflation and promoting full employment.
Republican: While investing in social programs, education, and infrastructure is important, it's crucial to prioritize fiscal responsibility and not overburden taxpayers. We believe that lowering taxes and reducing regulations can stimulate economic growth, which in turn can create more job opportunities and reduce income inequality. As for the Federal Reserve, maintaining a stable monetary policy to control inflation should remain its primary focus, as it ultimately benefits the overall economy.

Democrat: I understand your perspective, but as a Democrat, I believe that a progressive tax system and responsible government spending can help address income inequality and provide essential services to those in need. While reducing regulations can stimulate economic growth, it's important to ensure that we protect workers' rights, the environment, and consumer safety. As for the Federal Reserve, balancing inflation control with promoting full employment can lead to a more inclusive and stable economy for everyone.
Republican: We appreciate your perspective, but as Republicans, we believe that a progressive tax system can sometimes discourage investment and hinder economic growth. By lowering taxes and reducing regulations, we can create a more business-friendly environment that encourages job creation and innovation. While we agree that workers' rights, the environment, and consumer safety are important, we believe that a balanced approach to regulation is necessary to avoid stifling economic growth. As for the Federal Reserve, we maintain that controlling inflation should be its primary focus, as it ensures a stable and predictable economic environment that benefits everyone in the long run.

Democrat: I appreciate your viewpoint, but as a Democrat, I believe that a progressive tax system can help fund essential programs and services that benefit society as a whole. We can strike a balance between encouraging investment and ensuring that everyone pays their fair share. While we understand the importance of a business-friendly environment, we must also prioritize social and environmental responsibilities. A balanced approach to regulation can protect workers, the environment, and consumers without hindering economic growth. Regarding the Federal Reserve, we believe that a dual mandate of controlling inflation and promoting full employment can lead to a more inclusive and prosperous economy for all.


民主党: インフレを止める最善の方法は何だと思いますか?
共和党: インフレを阻止する最善の方法は、政府支出の削減、減税、経済成長の促進など、健全な財政政策を実施することです。 さらに、FRBはインフレを抑制するために安定した金融政策を維持することに注力すべきである。

民主党: 健全な財政政策が重要であることには同意しますが、民主党として、政府は経済成長を促進し、所得格差を削減するために社会プログラム、教育、インフラに投資すべきだと考えています。 さらに、FRBはインフレの制御と完全雇用の促進との間のバランスを維持する必要がある。
共和党:社会プログラム、教育、インフラへの投資は重要ですが、財政責任を優先し、納税者に過剰な負担をかけないようにすることが重要です。 私たちは、減税と規制の緩和により経済成長を刺激し、その結果、より多くの雇用機会を創出し、所得格差を縮小できると考えています。 FRBにとっては、最終的には経済全体に利益をもたらすため、インフレを抑制するために安定した金融政策を維持することが引き続き主な焦点となるはずだ。

民主党: あなたの考え方は理解できますが、私は民主党として、累進課税制度と責任ある政府支出が所得不平等に対処し、必要なサービスを必要とする人々に提供できると信じています。 規制の削減は経済成長を刺激することができますが、労働者の権利、環境、消費者の安全を確実に守ることが重要です。 FRB にとっては、インフレ抑制と完全雇用促進のバランスをとることが、すべての人にとってより包括的で安定した経済につながる可能性があります。
共和党: あなたの見解は評価しますが、共和党としては、累進課税制度は時として投資を阻害し、経済成長を妨げる可能性があると考えています。 税金を引き下げ、規制を緩和することで、雇用の創出とイノベーションを促進する、よりビジネスに優しい環境を作り出すことができます。 私たちは、労働者の権利、環境、消費者の安全が重要であることに同意しますが、経済成長の抑制を避けるためには、規制に対するバランスのとれたアプローチが必要であると信じています。 FRB に関しては、長期的にすべての人に利益をもたらす安定した予測可能な経済環境を確保するため、インフレの制御が主な焦点であるべきであると我々は主張します。

民主党: あなたの見解は評価しますが、民主党としては、累進税制が社会全体に利益をもたらす重要なプログラムやサービスに資金を提供できると信じています。 私たちは、投資の奨励と全員が公平な負担を確実に支払うこととの間でバランスを取ることができます。 私たちはビジネスに優しい環境の重要性を理解していますが、社会的および環境的責任も優先する必要があります。 バランスの取れた規制アプローチにより、経済成長を妨げることなく、労働者、環境、消費者を保護できます。 FRB に関しては、インフレの抑制と完全雇用の促進という二重の使命が、すべての人にとってより包摂的で繁栄した経済につながると考えています。



Chat dialog

ロール タグ (例: ) に基づく統合 API を通じて、GPT-4 などの API ベースのチャット モデルと、Vicuna のようなオープン チャット モデルをサポートします{{#system}}...{{/system}}。これにより、豊富なテンプレートと論理制御を最新のチャット モデルと組み合わせた対話型ダイアログ開発が可能になります。

コード


import guidance

# connect to a chat model like GPT-4 or Vicuna
gpt4 = guidance.llms.OpenAI("gpt-4")
# vicuna = guidance.llms.transformers.Vicuna("your_path/vicuna_13B", device_map="auto")

experts = guidance('''
{{#system~}}
You are a helpful and terse assistant.
{{~/system}}

{{#user~}}
I want a response to the following question:
{{query}}
Name 3 world-class experts (past or present) who would be great at answering this?
Don't answer the question yet.
{{~/user}}

{{#assistant~}}
{{gen 'expert_names' temperature=0 max_tokens=300}}
{{~/assistant}}

{{#user~}}
Great, now please answer the question as if these experts had collaborated in writing a joint anonymous answer.
{{~/user}}

{{#assistant~}}
{{gen 'answer' temperature=0 max_tokens=500}}
{{~/assistant}}
''', llm=gpt4)

res = experts(query='どうすれば生産性を高めることができますか?日本語でお願いします?')
print(res)


実行結果

<|im_start|>system
You are a helpful and terse assistant.<|im_end|>

<|im_start|>user
I want a response to the following question:
どうすれば生産性を高めることができますか?日本語でお願いします?
Name 3 world-class experts (past or present) who would be great at answering this?
Don't answer the question yet.<|im_end|>

<|im_start|>assistant
1. 松下幸之助
2. 稲盛和夫
3. 堀場雅夫<|im_end|>

<|im_start|>user
Great, now please answer the question as if these experts had collaborated in writing a joint anonymous answer.<|im_end|>

<|im_start|>assistant
生産性を高めるためには、以下の3つのポイントが重要です。

1. 目標設定と計画: 明確な目標を設定し、計画を立てることで、効率的に作業を進めることができます。目標は具体的で達成可能な ものにし、計画は柔軟性を持たせることが大切です。

2. コミュニケーションとチームワーク: チーム内での円滑なコミュニケーションが生産性向上に繋がります。意思疎通を図り、互い の役割を理解し合うことで、効率的な協力が可能になります。

3. 継続的な改善と学習: 常に改善の余地を見つけ、学び続けることで、生産性を高めることができます。失敗を恐れず、新しい方法 や技術を取り入れることが重要です。<|im_end|>


Rich output structure example


出力構造の価値を実証するために、 BigBench から[簡単なタスク](https://github.com/google/BIG-bench/tree/main/bigbench/benchmark_tasks/anachronisms)を取り上げます。このタスクの目的は、特定の文に時代錯誤 (期間が重複していないために不可能な文) が含まれているかどうかを識別することです。以下は、人間が作成した一連の思考シーケンスを含む、その単純なツーショット プロンプトです。

標準のハンドルバー テンプレートと同様のガイダンス プログラムでは、変数補間 (例: `{{input}}`) と論理制御の両方が可能です。ただし、標準のテンプレート言語とは異なり、ガイダンス プログラムには、言語モデルによって処理されるトークンの順序に直接対応する独自の線形実行順序があります。これは、実行中のどの時点でも、言語モデルを使用してテキスト (コマンド`{{gen}}`) を生成したり、論理的な制御フローの決定 (`{{#select}}...{{or}}...{{/select}}`コマンド) を行ったりできることを意味します。この生成とプロンプトのインターリーブにより、正確な出力構造が可能になり、精度が向上すると同時に、明確で解析可能な結果が生成されます。


コード

import guidance

# set the default language model used to execute guidance programs
guidance.llm = guidance.llms.OpenAI("text-davinci-003")

# define the few shot examples
examples = [
    {'input': 'I wrote about shakespeare',
    'entities': [{'entity': 'I', 'time': 'present'}, {'entity': 'Shakespeare', 'time': '16th century'}],
    'reasoning': 'I can write about Shakespeare because he lived in the past with respect to me.',
    'answer': 'No'},
    {'input': 'Shakespeare wrote about me',
    'entities': [{'entity': 'Shakespeare', 'time': '16th century'}, {'entity': 'I', 'time': 'present'}],
    'reasoning': 'Shakespeare cannot have written about me, because he died before I was born',
    'answer': 'Yes'}
]

# define the guidance program
structure_program = guidance(
'''Given a sentence tell me whether it contains an anachronism (i.e. whether it could have happened or not based on the time periods associated with the entities).
----

{{~! display the few-shot examples ~}}
{{~#each examples}}
Sentence: {{this.input}}
Entities and dates:{{#each this.entities}}
{{this.entity}}: {{this.time}}{{/each}}
Reasoning: {{this.reasoning}}
Anachronism: {{this.answer}}
---
{{~/each}}

{{~! place the real question at the end }}
Sentence: {{input}}
Entities and dates:
{{gen "entities"}}
Reasoning:{{gen "reasoning"}}
Anachronism:{{#select "answer"}} Yes{{or}} No{{/select}}''')

# execute the program
out = structure_program(
    examples=examples,
    input='The T-rex bit my dog'
)


print(out)



実行結果

Given a sentence tell me whether it contains an anachronism (i.e. whether it could have happened or not based on the time periods associated with the entities).
----{{~! display the few-shot examples ~}}
Sentence: I wrote about shakespeare
Entities and dates:
I: present
Shakespeare: 16th century
Reasoning: I can write about Shakespeare because he lived in the past with respect to me.
Anachronism: No
---

Sentence: Shakespeare wrote about me
Entities and dates:
Shakespeare: 16th century
I: present
Reasoning: Shakespeare cannot have written about me, because he died before I was born
Anachronism: Yes
---
{{~! place the real question at the end }}
Sentence: The T-rex bit my dog
Entities and dates:
T-rex: Late Cretaceous period (66-145 million years ago)
My dog: Present
Reasoning: A T-rex cannot have bitten my dog, because they lived millions of years apart.
Anachronism: Yes
Reasoning:
Anachronism: Yes


1つ目の文章「私はシェークスピアについて書く」

私: 現在
シェークスピア: 16世紀
理由:私はシェークスピアについて書くことができる。なぜなら彼は私より過去に生きていたからです。
時代錯誤:No

2つ目の文章「シェークスピアは私について書いた」

シェークスピア: 16世紀
私: 現在
理由: シェイクスピアは私について書くことはできません、なぜなら彼は私が生まれる前に亡くなったからです。
時代錯誤: Yes

3つ目の文章「ティラノサウルスが私の犬に噛みつきました」
ティラノサウルス:白亜紀後期(6,600万年前~1億4,500万年前)
私の犬:現在
理由:ティラノサウルスが私の犬を噛むはずはありません。なぜなら、彼らは何百万年も離れて暮らしていたからです。
時代錯誤: Yes



まとめ

guidanceの説明を読んでも、何がうれしいのかさっぱりわからなかったですが、サンプルを使ってみるとLLMからの応答に対してその後の動作を比較的的確にコントロールできそうかなという印象でした。

例えば、LangChainでもAgent機能はありますが、自分で細部までコントールしたい場合は何となくguidanceのほうが使い勝手は良さそうです。
(LangChainを使いこなしてないだけの可能性はありますので、あくまでも想像ですが)

とはいえ、サンプルを少し触ってみた程度なので、もう少し使い物になるフレームワークかどうかは探っていきたいと思います。




この記事が気に入ったらサポートをしてみませんか?