Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

almost weekly useful materials - 10/18 - #138

Open
GENZITSU opened this issue Sep 22, 2023 · 8 comments
Open

almost weekly useful materials - 10/18 - #138

GENZITSU opened this issue Sep 22, 2023 · 8 comments

Comments

@GENZITSU
Copy link
Owner

No description provided.

@GENZITSU
Copy link
Owner Author

GENZITSU commented Sep 22, 2023

RAG is more than just embedding search

シンプルなベクトルサーチベースの課題を述べながら、instructorというopenai function callingにpydanticを組み合わせられるライブラリを紹介している記事

挙げられている課題

  • Query-Document Mismatch
    • ユーザーからのクエリとドキュメントのembeddingは必ずしも空間上で近づかない場合がある。
  • Monolithic Search Backend:
    • 1つのサーチエンジンの結果だけに左右される
  • Limitation of text search:
    • シンプルな文章検索だと曖昧性のあるクエリに対応できない (ex. 「1週間前の進捗を教えて」というクエリそのままだと適切に検索ができない)
  • Limited ability to plan:
    • テキスト以外の情報、例えば場所や時間などの情報が欲しくなる

instructorを用いた解決策の提案

ユーザーのクエリに対して付与すべきメタ情報をLLMで抽出し、それを元に検索をすることでRAGの性能を上げる

class DateRange(BaseModel):
    start: datetime.date
    end: datetime.date

class MetaphorQuery(BaseModel):
    rewritten_query: str
    published_daterange: DateRange
    domains_allow_list: List[str]

    async def execute():
        return await metaphor.search(...)

import instructor 
import openai

# Enables response_model in the openai client
instructor.patch()

query = openai.ChatCompletion.create(
    model="gpt-4",
    response_model=MetaphorQuery,
    messages=[
        {
            "role": "system", 
            "content": "You're a query understanding system for the Metafor Systems search engine. Here are some tips: ..."
        },
        {
            "role": "user", 
            "content": "What are some recent developments in AI?"
        }
    ],
)
{
    "rewritten_query": "novel developments advancements ai artificial intelligence machine learning",
    "published_daterange": {
        "start": "2023-09-17",
        "end": "2021-06-17"
    },
    "domains_allow_list": ["arxiv.org"]
}

コメント

クエリ拡張をLLMで行うという方向性だが、どのような情報を拡張するかというのが設計者の腕の見せ所になりそう

出典

@GENZITSU
Copy link
Owner Author

GENZITSU commented Oct 5, 2023

Azure Cognitive Search: Outperforming vector search with hybrid retrieval and ranking capabilities

キーワード検索 と ベクトル検索の組み合わせたHybrid Search結果に検索結果のリランキングモデルを組み合わせることで、検索性能を大きく向上させることができたという報告

(これらの機能はAzure Cognitive Search上の設定で実施可能とのこと)

重要そうな結果

  • ハイブリッドサーチはキーワード検索+ベクトル検索のいいとこ取りとなる手法だがこれだけだと不十分で、リランキングで大きく精度が伸びる
  • ドキュメントをチャンキングする際の、token数はチューニングが大事
  • チャンキング時の分割方法 (トークン分割 or 文章分割 or N%オーバーラップ)もチューニングが大事
スクリーンショット 2023-10-05 15 23 21 スクリーンショット 2023-10-05 15 23 47 スクリーンショット 2023-10-05 15 23 55

検索部分

  • キーワード検索: ドキュメントをチャンキングした後、BM25文章の類似度で上位50件を抽出
  • ベクトル検索: text-embedding-ada-002 でベクトルにして、cos類似度で上位50件を抽出
  • ハイブリッド検索: 上記二つの検索で抽出した計100件の候補をReciprocal Rank Fusion (RRF) で 再度順位づけを行い、上位50件に改めて絞る。

※RRFのアルゴリズムはかなりシンプルで、順位の逆数に基づいたスコアを検索結果ごとに足し合わせて再度スコアを算出する以下のようなイメージのもの

スクリーンショット 2023-10-05 15 04 25

リランキング部分

  • あまり詳しいことは書かれていなかったが、deep learningベースのモデルで抽出した50件にスコアリングをして再度リランキングする
    • ここではqueryとdocumentsの類似度をtransformerモデルに入れてスコアリングしているとのこと
    • このモデルを学習させるためにはなんらかの教師データが必要?(事前学習済みモデルで行ける…?)
    • sentence transformersでいうcross-encoderのことを指している?
  • utilizes multi-lingual, deep learning models adapted from Microsoft Bing.
  • The semantic ranker runs the query and documents text simultaneously though transformer models that utilize the cross-attention mechanism to produce a ranker score.

検証設定について

DBからランダムにドキュメント片をGPTに入れて質問を生成してデータを作成

  • 他の記事でも見たことあるが、標準的なやり方?

We used a combination of end user queries and queries generated by several different GPT prompts using random snippets from the document index as grounding.

コメント

  • ハイブリッド検索はもはや当たり前のものになったんだなという印象
  • Fusion方法は計算速度的にRRFを使っているのだろうか?MRRなど工夫の余地ありそう
  • リランキングモデルが重要そうだが、これはレコメンド周りの方法が流用できるか?

出典

@GENZITSU
Copy link
Owner Author

GENZITSU commented Oct 5, 2023

10 Ways to Improve the Performance of Retrieval Augmented Generation Systems

RAGのパフォーマンスを向上させるための10の指針を紹介している記事

1. Clean your data.

  • ドキュメントのデータベースに入れたデータが利用しやすい形になっているかを確認する
    • 例えば同じトピックに関する文章が散逸している場合に、それらを統合しておく
    • 不要な文字列や記号などを消しておく
    • (私見) 文章自体がわかりやすくシンプルなものになっているかも重要

各ドキュメントのサマリーを作っておき、まずサマリーでマッチングを行い、そのサマリーとマッチするドキュメントの詳細を深掘りするという方法もある

2. Explore different index types.

検索indexを複数試す。キーワード + ベクトルなど

(私見) 日付やカテゴリなどのメタデータ付与とかも重要か?カテゴリはメンテナンスが大変そうではあるが

3. Experiment with your chunking approach.

chunking方法のチューニングは大事

  • とくにchunk sizeはとても重要なので、比較実験を行うべき
  • 複数のchunk sizeによる ensembleという方法もある
  • テキストをchunkに分割する方法にもいくつか方法がある
    • トークン数固定 / ピリオドなどの特定トークンによる分割 / 文章分割ライブラリによる分割 / 指定されたtoken数になるまで階層的に分割を行う方法

4. Play around with your base prompt.

プロンプトを変更する。

‘Context information is below. Given the context information and not prior knowledge, answer the query.’

‘You are a customer support agent. You are designed to be as helpful as possible while providing only factual information. You should be friendly, but not overly chatty. Context information is below. Given the context information and not prior knowledge, answer the query.’

5. Try meta-data filtering.

chunkにmeta dataを付与して、それによるフィルタリングを試す

例えば、時間に関するmeta dataを振ることで新しいものを優先的に見るなどが可能

6. Use query routing.

indexを複数分割しておき、このqueryが来た場合はこのindexを使うなどのroutingができるようにしておく。
ReActのtoolを作るかのような感じ。

7. Look into reranking.

候補文章のリランキング

cohereのre-rankerが性能良いとのこと

8. Consider query transformations.

  • 質問文を言い換えてみる
  • HyDEなどを試す
  • クエリを分解する

9. Fine-tune your embedding model.

ドメイン固有の文章の違いを判別できるようにembeddingモデルのfine tuningを行う

  • これだけで性能が5-10%が上がることもある

- 参考文献としてあげられていたもの,
- 分割したchunkを用いて、問題を作らせる方法でデータセットを作成する方法が紹介されていた。

10. Start using LLM dev tools.

デバッグしやすくなるようなツールを利用する

コメント

網羅的に整理されていて勉強になった

出典

@GENZITSU GENZITSU changed the title almost weekly useful materials - 10/04 - almost weekly useful materials - 10/18 - Oct 13, 2023
@GENZITSU
Copy link
Owner Author

Emojis Aid Social Media Sentiment Analysis: Stop Cleaning Them Out!

SNS投稿のセンチメント分析をする際の絵文字の扱いを検証している記事.
結論としては、絵文字の上は全て消し去るのではなく、何らかの方法でモデルの入力に含めることを勧ている。

Encoderによる挙動の違い

モデルによってはEncoderが絵文字のtokenizeに対応しているケースがある

検証対象は以下

  • ALBERT-base-v2
  • BERT-base, BERT-large
  • BERTweet-base, BERTweet-large
  • DeBERTa-base, DeBERTa-large
  • DistilBERT
  • RoBERTa-base, RoBERTa-large
  • Twitter-RoBERTa
  • XLMRoBERTa-base, XLMRoBERTa-large

下図のように、モデルによって扱えるemojiの種類に差があることがわかる。
→ 自分が利用するモデルがどれくらい扱えるか事前に調べた方がよい

スクリーンショット 2023-10-13 9 27 38

絵文字の処理方法

ブログ中では5種類言及されていた

  • encoderがtokenizeできるものはそのベクトル利用し、できないものはUNKとする
  • 絵文字をdescripstionに変換する
    • ex “I love animals 😍” will become “I love animals smiling face with heart-eyes.”
  • 絵文字の出現場所を最後に持っていく
    • ex “The cold weather is killing me🧊. Don’t wanna work any longer😡😭. ” becomes “The cold weather is killing me. Don’t wanna work any longer. 🧊😡😭”
  • 絵文字の出現場所を最後に持っていく & descriptionに変換
  • 絵文字の情報を文章情報とは独立させて、分類層の手前でconcatさせる

検証結果

少なくとも、絵文字の情報を消し去るよりはかは残して利用する方が良いことが示唆される。

また、絵文字の情報がtokenizerに入っているものについては、そのまま利用するのがシンプルかつベストで、絵文字のベクトルかが難しい場合はdescriptionに変更した方が良いとも考えられる。

Generally for BERT-based models, directly encoding emojis seems to be a sufficient and sometimes the best method. Surprisingly, the most straightforward methods work just as well as the complicated ones, if not better.

Poor emoji representation learning models might benefit more from converting emojis to textual descriptions.

スクリーンショット 2023-10-13 9 29 18

スクリーンショット 2023-10-13 9 29 24

スクリーンショット 2023-10-13 9 28 49

コメント

経験的にも絵文字を消すより、文章表現に直した方が精度が上がると思っていたので、それと整合する結果で安心。
最近のencoderは絵文字を直で扱えるものも多いことは新たな発見である。

出典

@GENZITSU
Copy link
Owner Author

GENZITSU commented Oct 13, 2023

Retrieval Augmented Generationを改良する2つの方法

表題の通り、2023年6月に書かれたものなので少し古いが、Microsoft Azureのサンプルに準拠した方法を紹介している。
1つめはユーザーとの会話履歴+質問からLLMが検索クエリを考えるというもので、二つ目は検索機能をtoolとして与えたReActにより自律的に該当文書を探す方法

よくある課題

  • ユーザーがクエリに利用する単語と参照ドキュメント中の単語が異なることで検索がうまくいかない
    • 「クエリ → 回答生成」が一問一答になり、会話の流れを考慮できない
  • 複数回の検索が必要なケースに対応できない
  • 検索結果に乗っている、別のリンクに問い合わせる必要がある場合

紹介されていた対応策

会話の履歴 + 質問文をもとにLLMが検索クエリを発行し、LLMが発行したクエリをもとにretrieveを行う

    - query_prompt_template = """Below is a history of the conversation so far, and a new question asked by the user that needs to be answered by searching in a knowledge base about employee healthcare plans and the employee handbook.
You have access to Azure Cognitive Search index with 100's of documents.
Generate a search query based on the conversation and the new question.
Do not include cited source filenames and document names e.g info.txt or doc.pdf in the search query terms.
Do not include any text inside [] or <<>> in the search query terms.
Do not include any special characters like '+'.
If the question is not in English, translate the question to English before generating the search query.
If you cannot generate a search query, return just the number 0.
"""

検索機能をツールとして与えたAgentを作成して、検索の必要有無 / 検索クエリ の発行をAgentに任せる

  • 仕組み自体は理解しやすいが、ReActのexampleを書くのが結構大変そう (サンプルでは100行以上書かれていた)
llm = AzureOpenAI(deployment_name=self.openai_deployment, temperature=overrides.get("temperature") or 0.3, openai_api_key=openai.api_key)
tools = [
    Tool(name="Search", func=lambda q: self.search(q, overrides), description="useful for when you need to ask with search", callbacks=cb_manager),
    Tool(name="Lookup", func=self.lookup, description="useful for when you need to ask with lookup", callbacks=cb_manager)
]

# Like results above, not great to keep this as a global, will interfere with interleaving
global prompt
prompt_prefix = overrides.get("prompt_template")
prompt = PromptTemplate.from_examples(
    EXAMPLES, SUFFIX, ["input", "agent_scratchpad"], prompt_prefix + "\n\n" + PREFIX if prompt_prefix else PREFIX)

agent = ReAct.from_llm_and_tools(llm, tools)
chain = AgentExecutor.from_agent_and_tools(agent, tools, verbose=True, callback_manager=cb_manager)
result = chain.run(q)

コメント

  • 検索クエリを考えてもらう部分は、業界固有の単語が少ない場合はうまくいきそうだが、専門用語が多い場合にちゃんとクエリを発行できるのかが心配
    • 場合によってはLLMのfine tuningが必要か?
  • ReAct部分は原理はわかるがチューニングがめちゃ大変そう...

出典

@GENZITSU
Copy link
Owner Author

ベクトル検索で欲しい情報が得られないときの問題点と改良方法を考えてみた

表題の通り

2023/7の記事だがよく整理されている

考えられる問題点

  • 質問とソース文章の文体が異なる
    • 例えば、質問のテキストでは「〇〇についてわからないのですが、どうしたら良いか教えてください」のように書かれ、社内文章などの文章では「〇〇の方法」「〇〇の際は以下から手続きしてください」のように書かれていることが想定され、文体などが異なることが多そうです。
  • 質問とソース文章が意味的に近づかない
    • 意味的に類似していることよりも、ソース文章が質問に回答できるかという観点で取得したい
  • 条件に沿ったfilter処理はできない
    • 複数回の検索が必要になる場合がある
  • ユーザーのクエリ自体に情報が不足している場合がある
    • 状況に合わせて、質問の補完や追加の質問、状況の推定、ユーザーの誤り訂正などができる必要がある

方針

  • ユーザーのクエリを変換させる

スクリーンショット 2023-10-13 11 29 31

  • データベースの整形
    • ソースドキュメントからQAを生成しておき、生成したQAとクエリの類似度を測る
    • 作成したQAのうちどこをベクトル化するかは要比較

スクリーンショット 2023-10-13 11 29 39

  • ドキュメントに様々な補足情報をつける

スクリーンショット 2023-10-13 11 29 49

  • 類似度の判定方法を変更する (Two-Towerモデルの利用)
    • ただし、学習データが必要となる
    • 整備済みのQAやQAデータセットを新たに作成して、学習データを作成する方法が考えられるか
    • qa用の学習済みモデルもある。参考

スクリーンショット 2023-10-13 11 30 01

  • 文章抽出の範囲を拡大させる
    • 抽出時に該当箇所の前後も含めてretrieveする
    • 文章の階層構造を踏まえて、上下階層の情報を抽出する
    • テキストのチャンクサイズを大きくする
    • ベクトル検索以外の検索方法と組み合わせる
  • Agentを利用して複数回検索に対応させる
    • 実際は、挙動の統制を取るのが難しいらしい

コメント

よくまとまっていて参考になる

出典

@GENZITSU
Copy link
Owner Author

GENZITSU commented Oct 13, 2023

Google Cloud Enterprise SearchとRetrieveReadCompose方式RAGを利用して社内公式情報を全部質問できるようにしてみた

情報検索後、検索結果から関連情報をLLMに抽出させた後に、Generationを行うというちょっと変わったRAGを実践している記事

アーキテクチャ

スクリーンショット 2023-10-13 15 27 06

  • Retrieve: 必要な情報が含まれているであろうファイルのチャンク + そのファイルへのパスを抜き出す
  • Read: 抽出したチャンクから質問に関連する情報だけを抜き出す
    • Retreiveしたチャンクから不要な情報を削除し回答の質を向上させると同時にとトークン数を節約可能
    • 抜き出しだけであれば安価なLLMで実行可能
    • ドキュメントのファイルパスに情報が含まれている場合はこれを参考情報として入れると回答の質が良くなるとのこと
USER_PROMPT_FORMAT_EXTRACT_INFO = """
ユーザからの質問と、その回答として利用できるかわかっていないドキュメントがあります。
ドキュメントがユーザの質問に対する回答に使用できそうな情報を取り出してください。
ドキュメントはデータベースに保存されており、そのファイルパスが与えられるので考慮にいれてください。
回答に使用できそうな情報は箇条書きで出力してください。

# 制約
- 使用できそうな情報のみ回答してください
- 出力はJSON形式で、Stringのリストで回答してください
- 使用できそうな情報がない場合は空のリスト"[]"を出力してください。

# 出力の例
["明日の天気は晴れです", "明後日の天気は曇りです"]

# ユーザからの質問
{user_question}

# ドキュメントのファイルパス
{document_filepath}

# ドキュメントの内容
{document_text}
""".strip()
  • Compose: 抜き出した情報をもとに最終的な回答を生成する
    • Compose時もドキュメントのファイルパスを与えることで回答の質が向上
    • 引用形式にすることで見やすく
USER_PROMPT_FORMAT_GENERAGE_ANSWER = """
ユーザからの質問と、その回答で利用できる情報があります。
ドキュメントの情報をもとに、ユーザの質問に対する回答を生成してください。
ドキュメントはデータベースに保存されており、そのファイルパスが与えられるので考慮にいれてください。
矛盾している内容がある場合は、その旨を回答してください。
使用したドキュメントは、その番号を引用の形式で示してください 例:[0],[2]

# 制約
- 質問に関係のありそうな情報にのみ基づいて回答してください。

# ドキュメントのファイルパスと内容
{available_info}

# ユーザからの質問
{user_question}

# 回答
""".strip()

その他改良方針

  • Retrieveの件数
    • top 10件を抽出したとのことだが、実際は6件程度でも良さそうとのこと
    • Read部分で利用するモデル
    • またgpt3.5→gpt4.0に変更することで、不要な情報の抜き出しが抑えられるとのこと
  • 状況設定の追加
    • 「クラスメソッド株式会社というIT会社において、社内の公式情報をドキュメントから検索しようとしています」
    • 「社内では、Slackというコミュニケーションツールを活用し、何か困ったことがあればReinforcement Learning Inside Business #1-help-meというチャンネルで質問すると、誰かが回答してくれます」
  • ドキュメントの階層構造を用いたRetrieve
  • 質問ユーザーの情報追加
    • 質問をしたユーザがどういった人物なのか、いつ検索を行っているのかといった情報も含めると、より具体的なガイダンスが可能になりそうです。
  • ドキュメントの質自体の向上
    • 誤った回答が生成される原因の多くは、ドキュメント自体のわかりにくさ
    • ドキュメント自体をLLMに書き直させるなど

料金

1回の生成あたり10 ~20円

処理時間

全体:32.6[s]

  • Retrieve部分:1.22[s]
  • Read部分:12.68[s]
  • Compose部分:18.65[s]

コメント

システムを組み上げるせいに工夫した点や改良すべき点も述べられていて勉強になる

Read機構の存在を前提とするなら、検索部分は粗く広く取れれば良いので、ドキュメントのチャンクサイズを大きめにしておくとか、検索結果のtopNを多めにしておくなどの対応が取れて、検索負荷が下がりそう。

出典

@GENZITSU
Copy link
Owner Author

GENZITSU commented Oct 13, 2023

セキュリティチェックシートに回答する“つらみ”はLLMで解消 ~セキュリティ担当者に「本格運用できるんじゃない?」と言わせた仕組み~

過去のセキュリティチェックシートの回答結果を用いてRAGによって新たなシートに回答を行う取り組みについて紹介している記事

全体像

スクリーンショット 2023-10-13 17 42 54

工夫点

参考にした回答結果のはい/いいえに引っ張られることがあるので、参考情報を一度要約させている

スクリーンショット 2023-10-13 17 43 49

スクリーンショット 2023-10-13 17 43 44

コメント

こういう細かな工夫点大事

出典

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant