AIパーソナル・ラーニング
と実践的なガイダンス
讯飞绘镜

DB-GPTの実世界シナリオにおけるRAG最適化に関する10,000語の記事。

序文

この2年間で、検索・拡張生成(RAG、Retrieval-Augmented Generation)技術は徐々に強化された知能の中核的な要素となってきた。検索と生成の2つの機能を組み合わせることで、RAGは外部知識を導入することができ、その結果、複雑なシナリオにおける大規模モデルの適用により多くの可能性を提供することができる。しかしながら、実用的な着地シナリオにおいては、検索精度の低さ、ノイズ干渉、想起の完全性、不十分な専門性などの問題がしばしば発生し、深刻なLLM錯覚につながる。本論文では、実際の着陸シナリオにおけるRAGの知識処理と検索の詳細に焦点を当て、最終的に想起精度を向上させるためにRAG Pineline linkを最適化する方法について述べる。

 


RAGスマートQ&Aアプリを素早く構築するのは簡単だが、実際のビジネスシナリオに落とし込むには多くの準備が必要だ。

 

1.RAGキープロセス・ソースコードの解釈

センター知識処理歌で応えるラグ主要なプロセスをいくつか紹介しよう:

1.知識処理

知識ロード→知識スライシング→情報抽出→知識処理(埋め込み/グラフ/キーワード)→知識ストレージ

 

 

  • ナレッジ・ローディング
# 知识工厂进行实例化
KnowledgeFactory -> create() -> load() -> Document
- knowledge
- markdown
- pdf
- docx
- txt
- html
- pptx
- url
- ...

 

拡大する方法

from abc import ABC
from typing import List, Any

class Knowledge(ABC):
def load(self) -> List[Document]:
"""Load knowledge from data loader."""
pass

@classmethod
def document_type(cls) -> Any:
"""Get document type."""
pass

@classmethod
def support_chunk_strategy(cls) -> List[ChunkStrategy]:
"""Return supported chunk strategy."""
return [
ChunkStrategy.CHUNK_BY_SIZE,
ChunkStrategy.CHUNK_BY_PAGE,
ChunkStrategy.CHUNK_BY_PARAGRAPH,
ChunkStrategy.CHUNK_BY_MARKDOWN_HEADER,
ChunkStrategy.CHUNK_BY_SEPARATOR,
]

@classmethod
def default_chunk_strategy(cls) -> ChunkStrategy:
"""
Return default chunk strategy.

Returns:
ChunkStrategy: default chunk strategy
"""
return ChunkStrategy.CHUNK_BY_SIZE

 

  • ナレッジスライス

 

 

ChunkManager: ユーザーが指定したチャンキングポリシーとチャンキングパラメータに基づいて、ロードされた知識データを対応するチャンクプロセッサにルーティングし、割り当てを行う。

class ChunkManager:
"""Manager for chunks."""

def __init__(
self,
knowledge: Knowledge,
chunk_parameter: Optional[ChunkParameters] = None,
extractor: Optional[Extractor] = None,
):
"""
Create a new ChunkManager with the given knowledge.

Args:
knowledge: (Knowledge) Knowledge datasource.
chunk_parameter: (Optional[ChunkParameters]) Chunk parameter.
extractor: (Optional[Extractor]) Extractor to use for summarization.
"""
self._knowledge = knowledge
self._extractor = extractor
self._chunk_parameters = chunk_parameter or ChunkParameters()
self._chunk_strategy = (
chunk_parameter.chunk_strategy
if chunk_parameter and chunk_parameter.chunk_strategy
else self._knowledge.default_chunk_strategy().name
)
self._text_splitter = self._chunk_parameters.text_splitter
self._splitter_type = self._chunk_parameters.splitter_type

 

拡張方法:インターフェイスで新しいスライス戦略をカスタマイズしたい場合

  • 新しいスライス戦略
  • 新しいスプリッター実装ロジック
class ChunkStrategy(Enum):
"""Chunk Strategy Enum."""

CHUNK_BY_SIZE: _STRATEGY_ENUM_TYPE = (
RecursiveCharacterTextSplitter,
[
{
"param_name": "chunk_size",
"param_type": "int",
"default_value": 512,
"description": "The size of the data chunks used in processing.",
},
{
"param_name": "chunk_overlap",
"param_type": "int",
"default_value": 50,
"description": "The amount of overlap between adjacent data chunks.",
},
],
"chunk size",
"split document by chunk size",
)

CHUNK_BY_PAGE: _STRATEGY_ENUM_TYPE = (
PageTextSplitter,
[],
"page",
"split document by page",
)

CHUNK_BY_PARAGRAPH: _STRATEGY_ENUM_TYPE = (
ParagraphTextSplitter,
[
{
"param_name": "separator",
"param_type": "string",
"default_value": "\n",
"description": "paragraph separator",
}
],
"paragraph",
"split document by paragraph",
)

CHUNK_BY_SEPARATOR: _STRATEGY_ENUM_TYPE = (
SeparatorTextSplitter,
[
{
"param_name": "separator",
"param_type": "string",
"default_value": "\n",
"description": "chunk separator",
},
{
"param_name": "enable_merge",
"param_type": "boolean",
"default_value": False,
"description": (
"Whether to merge according to the chunk_size after "
"splitting by the separator."
),
},
],
"separator",
"split document by separator",
)

CHUNK_BY_MARKDOWN_HEADER: _STRATEGY_ENUM_TYPE = (
MarkdownHeaderTextSplitter,
[],
"markdown header",
"split document by markdown header",
)

 

  • 知識抽出
  • ベクトル抽出→埋め込み、実装Embeddingsコネクタ
@abstractmethod
def embed_documents(self, texts: List[str]) -> List[List[float]]:
"""Embed search docs."""

@abstractmethod
def embed_query(self, text: str) -> List[float]:
"""Embed query text."""

async def aembed_documents(self, texts: List[str]) -> List[List[float]]:
"""Asynchronous Embed search docs."""
return await asyncio.get_running_loop().run_in_executor(
None, self.embed_documents, texts
)

async def aembed_query(self, text: str) -> List[float]:
"""Asynchronous Embed query text."""
return await asyncio.get_running_loop().run_in_executor(
None, self.embed_query, text
)

 

# EMBEDDING_MODEL=proxy_openai
# proxy_openai_proxy_server_url=https://api.openai.com/v1
# proxy_openai_proxy_api_key={your-openai-sk}
# proxy_openai_proxy_backend=text-embedding-ada-002

## qwen embedding model, See dbgpt/model/parameter.py
# EMBEDDING_MODEL=proxy_tongyi
# proxy_tongyi_proxy_backend=text-embedding-v1
# proxy_tongyi_proxy_api_key={your-api-key}

## qianfan embedding model, See dbgpt/model/parameter.py
# EMBEDDING_MODEL=proxy_qianfan
# proxy_qianfan_proxy_backend=bge-large-zh
# proxy_qianfan_proxy_api_key={your-api-key}
# proxy_qianfan_proxy_api_secret={your-secret-key}

 

  • 知識グラフ抽出→知識グラフ
class TripletExtractor(LLMExtractor):
"""TripletExtractor class."""

def __init__(self, llm_client: LLMClient, model_name: str):
"""Initialize the TripletExtractor."""
super().__init__(llm_client, model_name, TRIPLET_EXTRACT_PT)

TRIPLET_EXTRACT_PT = (
"Some text is provided below. Given the text, "
"extract up to knowledge triplets as more as possible "
"in the form of (subject, predicate, object).\n"
"Avoid stopwords. The subject, predicate, object can not be none.\n"
"---------------------\n"
"Example:\n"
"Text: Alice is Bob's mother.\n"
"Triplets:\n(Alice, is mother of, Bob)\n"
"Text: Alice has 2 apples.\n"
"Triplets:\n(Alice, has 2, apple)\n"
"Text: Alice was given 1 apple by Bob.\n"
"Triplets:(Bob, gives 1 apple, Alice)\n"
"Text: Alice was pushed by Bob.\n"
"Triplets:(Bob, pushes, Alice)\n"
"Text: Bob's mother Alice has 2 apples.\n"
"Triplets:\n(Alice, is mother of, Bob)\n(Alice, has 2, apple)\n"
"Text: A Big monkey climbed up the tall fruit tree and picked 3 peaches.\n"
"Triplets:\n(monkey, climbed up, fruit tree)\n(monkey, picked 3, peach)\n"
"Text: Alice has 2 apples, she gives 1 to Bob.\n"
"Triplets:\n"
"(Alice, has 2, apple)\n(Alice, gives 1 apple, Bob)\n"
"Text: Philz is a coffee shop founded in Berkeley in 1982.\n"
"Triplets:\n"
"(Philz, is, coffee shop)\n(Philz, founded in, Berkeley)\n"
"(Philz, founded in, 1982)\n"
"---------------------\n"
"Text: {text}\n"
"Triplets:\n"
)

 

    • 逆インデックス抽出→キーワードセグメンテーション
      • esのデフォルト辞書を使用することもできるし、esのプラグインモードを使用して辞書をカスタマイズすることもできる。
  • ナレッジ・ストレージ

全体的な知識の持続性は一様に達成されるIndexStoreBase現在、ベクトル・データベース、グラフ・データベース、フルテキスト・インデキシングの3種類の実装を提供している。

  • VectorStore、ベクターデータベースのメインロジックはload_document()にあり、インデックススキーマの作成、ベクターデータの一括書き込みなどが含まれる。
# Base class hierarchy
- VectorStoreBase
- ChromaStore
- MilvusStore
- OceanbaseStore
- ElasticsearchStore
- PGVectorStore

# Base class definition
class VectorStoreBase(IndexStoreBase, ABC):
"""
Vector store base class.
"""

@abstractmethod
def load_document(self, chunks: List[Chunk]) -> List[str]:
"""
Load document in index database.
"""
pass

@abstractmethod
async def aload_document(self, chunks: List[Chunk]) -> List[str]:
"""
Load document in index database asynchronously.
"""
pass

@abstractmethod
def similar_search_with_scores(
self,
text: str,
topk: int,
score_threshold: float,
filters: Optional[MetadataFilters] = None,
) -> List[Chunk]:
"""
Perform a similar search with scores in the index database.
"""
pass

def similar_search(
self,
text: str,
topk: int,
filters: Optional[MetadataFilters] = None,
) -> List[Chunk]:
"""
Perform a similar search in the index database.
"""
return self.similar_search_with_scores(text, topk, 1.0, filters)

 

  • GraphStore、具象グラフ・ストアは、3値書き込みの実装を提供する。これは一般に、具象グラフ・データベースのクエリー言語を呼び出すことで行われる。例えばTuGraphStore特定のCypher文が生成され、三項に基づいて実行される。
    • グラフ・ストレージ・インターフェース GraphStoreBase は、グラフ・ストレージのための統一された抽象化を提供する。MemoryGraphStore歌で応えるTuGraphStoreを実装し、開発者がアクセスできるようにNeo4jインターフェースも提供している。
# GraphStoreBase -> TuGraphStore -> Neo4jStore
def insert_triplet(self, subj: str, rel: str, obj: str) -> None:
"""Add triplet."""
# Create queries to merge nodes and relationship
subj_query = f"MERGE (n1:{self._node_label} {{id:'{subj}'}})"
obj_query = f"MERGE (n2:{self._node_label} {{id:'{obj}'}})"
rel_query = (
f"MERGE (n1:{self._node_label} {{id:'{subj}'}})"
f"-[r:{self._edge_label} {{id:'{rel}'}}]->"
f"(n2:{self._node_label} {{id:'{obj}'}})"
)
# Execute queries
self.conn.run(query=subj_query)
self.conn.run(query=obj_query)
self.conn.run(query=rel_query)

 

    • FullTextStore: es のインデックスを構築し、es 組み込みの単語分割アルゴリズムで単語分割を行い、es で keyword->doc_id の転置インデックスを構築する。
{
"analysis": {
"analyzer": {
"default": {
"type": "standard"
}
}
},
"similarity": {
"custom_bm25": {
"type": "BM25",
"k1": self._k1,
"b": self._b
}
}
}

self._es_mappings = {
"properties": {
"content": {
"type": "text",
"similarity": "custom_bm25"
},
"metadata": {
"type": "keyword"
}
}
}

# FullTextStoreBase
# ElasticDocumentStore
# OpenSearchStore

 

2.知識検索

question -> rewrite -> similarity_search -> rerank -> context_candidates

次に、知識検索ですが、現在のコミュニティ検索ロジックは主に以下のステップに分かれています:クエリ書き換えパラメータを設定した場合、現在、大きなモデルを通して質問の書き換えのラウンドを与えます。リランクモデルを設定すると、粗いスクリーニングの後に細かいスクリーニングを行い、候補値をよりユーザの質問に関連したものにします。

  • エンベッディングレトリバー
class EmbeddingRetriever(BaseRetriever):
"""Embedding retriever."""

def __init__(
self,
index_store: IndexStoreBase,
top_k: int = 4,
query_rewrite: Optional[QueryRewrite] = None,
rerank: Optional[Ranker] = None,
retrieve_strategy: Optional[RetrieverStrategy] = RetrieverStrategy.EMBEDDING,
):
pass

async def _aretrieve_with_score(
self,
query: str,
score_threshold: float,
filters: Optional[MetadataFilters] = None,
) -> List[Chunk]:
"""
Retrieve knowledge chunks with score.

Args:
query (str): Query text.
score_threshold (float): Score threshold.
filters: Metadata filters.

Returns:
List[Chunk]: List of chunks with score.
"""
queries = [query]

new_queries = await self._query_rewrite.rewrite(
origin_query=query,
context=context,
nums=1
)
queries.extend(new_queries)

candidates_with_score = [
self._similarity_search_with_score(
query,
score_threshold,
filters,
root_tracer.get_current_span_id()
)
for query in queries
]

new_candidates_with_score = await self._rerank.arank(
new_candidates_with_score,
query
)

return new_candidates_with_score
    • index_store: 特定のベクトル・データベース
    • top_k: 返されるチャンク候補の数。
    • query_rewrite: クエリ書き換え関数
    • rerank: 並べ替え機能
    • query:オリジナルクエリー
    • score_threshold: スコア、デフォルトでは類似度スコアがしきい値以下のコンテキストをフィルタリングする。
    • フィルターがある:Optional[MetadataFilters]メタデータ情報フィルターは、主に属性情報を通して前面にいくつかの不一致の候補情報をふるいにかけるために使用することができます。
from enum import Enum
from typing import Union, List
from pydantic import BaseModel, Field

class FilterCondition(str, Enum):
"""Vector Store Meta data filter conditions."""
AND = "and"
OR = "or"

class MetadataFilter(BaseModel):
"""Meta data filter."""
key: str = Field(
..., 
description="The key of metadata to filter."
)
operator: FilterOperator = Field(
default=FilterOperator.EQ, 
description="The operator of metadata filter."
)
value: Union[str, int, float, List[str], List[int], List[float]] = Field(
..., 
description="The value of metadata to filter."
)

 

まず、キーワードの抽出はモデルを通じて行われ、ここでは単語分割のための伝統的なnlp技法、または単語分割のための大きなモデルを通じて行うことができ、次に、キーワードは、キーワード候補リストを見つけるために、展開を行うために同義語に従って行われ、キーワード候補リストに従って局所部分グラフを呼び出すために、探索法を呼び出す方がよい。

KEYWORD_EXTRACT_PT = (
"A question is provided below. Given the question, extract up to "
"keywords from the text. Focus on extracting the keywords that we can use "
"to best lookup answers to the question.\n"
"Generate as more as possible synonyms or alias of the keywords "
"considering possible cases of capitalization, pluralization, "
"common expressions, etc.\n"
"Avoid stopwords.\n"
"Provide the keywords and synonyms in comma-separated format."
"Formatted keywords and synonyms text should be separated by a semicolon.\n"
"---------------------\n"
"Example:\n"
"Text: Alice is Bob's mother.\n"
"Keywords:\nAlice,mother,Bob;mummy\n"
"Text: Philz is a coffee shop founded in Berkeley in 1982.\n"
"Keywords:\nPhilz,coffee shop,Berkeley,1982;coffee bar,coffee house\n"
"---------------------\n"
"Text: {text}\n"
"Keywords:\n"
)

def explore(
self,
subs: List[str],
direct: Direction = Direction.BOTH,
depth: Optional[int] = None,
fan: Optional[int] = None,
limit: Optional[int] = None,
) -> Graph:
"""Explore on graph."""

 

  • DBSchemaRetrieverこれは、ChatDataシナリオのスキーマリンク検索でもある。

    主にスキーマリンク方式で二段階の類似性検索を行い、最初に最も関連性の高いテーブルを見つけ、次に最も関連性の高いフィールド情報を見つける。

    長所:この2段階検索は、大型ワイドテーブルの経験に関するコミュニティからのフィードバックに対応するためのものでもある。

def _similarity_search(self, query, filters: Optional[MetadataFilters] = None) -> List[Chunk]:
"""Similar search."""

# Perform similarity search with scores
table_chunks = self._table_vector_store_connector.similar_search_with_scores(
query, self._top_k, 0, filters
)

# Filter out chunks with 'separated' metadata
not_sep_chunks = [
chunk for chunk in table_chunks if not chunk.metadata.get("separated")
]
separated_chunks = [
chunk for chunk in table_chunks if chunk.metadata.get("separated")
]

# If no separated chunks, return the non-separated chunks
if not separated_chunks:
return not_sep_chunks

# Create tasks list for retrieving fields from separated chunks
tasks = [
lambda c=chunk: self._retrieve_field(c, query) for chunk in separated_chunks
]

# Run tasks concurrently with a concurrency limit of 3
separated_result = run_tasks(tasks, concurrency_limit=3)

# Combine and return results
return not_sep_chunks + separated_result

 

    • table_vector_store_connector: 最も関連性の高いテーブルを検索する。
    • field_vector_store_connector: 最も関連性の高いフィールドを検索する。

 

2.知識処理、知識検索の最適化アイデア

現在、RAGスマートクイズアプリにはいくつかのペインポイントがある:

  • 知識ベース内の文書が増えると、検索にノイズが入り、想起精度は高くならない
  • 不完全なリコールと完全性の欠如
  • リコールとユーザーの質問意図はほとんど関連性がない
  • 静的なデータにしか答えられず、知識に動的にアクセスできないため、退屈で間抜けな回答アプリケーションになってしまう。

1. 知識処理の最適化

非構造化/半構造化/構造化データの処理は、RAGアプリケーションの上限を決定する準備が整っているので、まずは知識処理、インデックス作成段階、そしてアイデアの方向性の主な最適化において、多くのきめ細かいETL作業を行う必要がある:

  • 非構造化→構造化:知識情報を構造的に整理する。
  • より豊かで多様な意味情報を抽出する。

 1.1 ナレッジ・ローディング

目的:異なるタイプのデータをより多様な方法で識別するためには、ドキュメントの正確な構文解析が必要である。

最適化の推奨

  • docxやtxtなどのテキストは、pdfやmarkdown形式で処理する前に、テキストの内容をよりよく抽出するための認識ツールを使用できるようにすることをお勧めします。
  • テキストからテーブル情報を抽出する。
  • 次の階層関係ツリーや他のインデックス作成方法のために、マークダウンやpdfのタイトルの階層情報を保持する。
  • 画像リンク、数式、その他の情報を保持し、マークダウン形式に統一する。

 1.2 チャンクをできるだけそのままスライスする

目的:文脈の完全性と関連性を維持する。

チャンキングによって、LLMへのテキスト入力がトークンの制限を超えないようにする。

最適化の推奨

  • 画像と表は別々のチャンクとして抽出され、表と画像のキャプションはメタデータのメタデータに保持される。
  • 文書コンテンツは、ヘッダー階層またはMarkdownヘッダーに従って可能な限り分割され、可能な限りチャンクの整合性が保たれます。
  • カスタムセパレーターがある場合は、カスタムセパレーターでスライスできます。

 1.3 多様な情報抽出

文書の埋め込みベクトル抽出に加えて、他の多様な情報抽出は、文書のデータを強化し、大幅にRAGリコール効果を向上させることができます。

  • ナレッジマップ
      • 利点:1.NativeRAGの完全性の欠如に対処し、まだ錯覚の問題があり、知識の境界の完全性、知識の構造と意味論の明快さを含む知識の正確さは、類似検索の能力を意味的に補完するものである。
      • シナリオ:知識の準備に制約が必要で、知識間の階層関係が明確に確立できる厳格な専門領域(ヘルスケア、O&Mなど)向け。
      • どうすれば達成できるか:

        1.大きなモデルに依存して、(エンティティ,リレーションシップ,エンティティ)の3項関係を抽出する。

        2.知識グラフを構築するために、手動またはカスタムSOPプロセスによるビジネスルールを通じて、事前品質、構造化された知識の準備、クリーニング、抽出に頼る。

  • ドク・ツリー
      • 適用可能なシナリオ:コンテキストの完全性が不十分であるという問題を解決するだけでなく、セマンティクスとキーワードのみに基づいてマッチングを行い、ノイズを減らすことができる。
      • 実現方法:タイトルレベルでチャンクのツリーノードを構築して多項ツリー構造を形成し、各レベルノードにはドキュメントのタイトルのみを格納し、リーフノードには特定のテキストコンテンツを格納する。このように、ツリー・トラバーサル・アルゴリズムを使用すると、ユーザーの質問が関連する非リーフ・タイトル・ノードにヒットした場合、関連する子ノードのデータを呼び出すことができる。こうすることで、チャンクの整合性不足の問題は発生しない。

フィーチャーのこの部分は、来年早々にもコミュニティに投入する予定だ。

  • QAペアの抽出には、定義済みまたはモデル抽出法によるQAペア情報のフロントエンド抽出が必要である。
    • 適用されるシナリオ
      • 検索および直接リコールの質問を打つ機能は直接ユーザーがほしい答えを、あるFAQのシナリオに適当取り出す、リコールの完全性は十分なシナリオでない。
    • どうすれば達成できるか:
      • 事前定義:各チャンクにいくつかの質問を事前に追加します。
      • モデル抽出:コンテキストが与えられたら、モデルにQAペア抽出を行わせる。

 

  • メタデータ抽出
    • 実現方法:自社のビジネスデータの特性に応じて、タグ、カテゴリー、時間、バージョン、その他のメタデータ属性など、保持するデータの特性を抽出する。
    • 適用可能なシナリオ:メタデータの属性に基づいて検索を事前にフィルタリングし、ノイズの大部分を取り除くことができる。
  • 要約と抜粋
    • 適用シナリオ:解決这篇文章讲了个啥总结一下などの世界的な問題シナリオがある。
    • 実装方法:Mapreduceなどによる分割抽出、モデルによる各チャンクのサマリー情報の抽出。

 1.4 知識処理のワークフロー

現在のところ DB-GPT 知識ベースは、文書のアップロード→構文解析→スライシング→埋め込み→知識グラフ三項抽出→ベクトルデータベース保存→グラフデータベース保存などの知識処理機能を提供するが、文書から複雑でパーソナライズされた情報を抽出する機能は持っていないため、知識処理ワークフローテンプレートを構築することで、複雑で、視覚的で、ユーザ定義可能な知識抽出、変換、処理プロセスを完成させることが望まれている。そこで、複雑で、視覚的で、ユーザー定義可能な知識抽出、変換、処理プロセスを完成させる知識処理ワークフローテンプレートを構築することが望まれている。

知識処理のワークフロー:

https://www.yuque.com/eosphoros/dbgpt-docs/vg2gsfyf3x9fuglf

2.RAGプロセスの最適化RAGプロセスの最適化は、静的な文書のRAGと動的なデータの取得RAGに細分化され、現在のRAGのほとんどは、非構造化文書の静的な資産をカバーするだけでなく、Q&Aの多くのシナリオの実際のビジネスは、動的なデータ+静的な知識データを取得するツールを介して一緒にシナリオに答えるために、静的な知識を取得するだけでなく、RAGする必要があります。ツール資産ライブラリのツールの情報を取得し、動的データの取得を実行します。

 2.1 静的知識RAGの最適化

(1) 当初の問題の処理

目的:ユーザーのセマンティクスを明確にし、ユーザーの元の質問を、あいまいで意図的でないクエリから、意味の豊かな検索可能なクエリに最適化する。

  • 生問題の分類。
    • LLMの分類(LLMExtractor)
    • 埋め込み+ロジスティック回帰を構築して2タワーモデルを実装する text2nlu DB-GPT-Hub/src/dbgpt-hub-nlu/README.zh.md at main - eosphoros-ai/DB-GPT-Hub
      • 先端: 良質の埋め込まれたモデルが必要、bge-v1.5-large を推薦して下さい

  • ユーザーに質問を返し、意味が明確でない場合は、質問を明確にするためにユーザーに質問を投げ返す。
    • 検索可能なシソーラスを使用して、意味的な関連性に基づいてユーザーに質問のショートリストを提案します。
  • スロットの抽出。ユーザーの質問から、意図、ビジネス属性などの重要なスロット情報を取得することを目的とする。
    • LLM抽出(LLMExtractor)
  • 質問を書き換える
    • ホット・サーチ・シソーラスの書き換え
    • 重層的相互作用
(2) メタデータのフィルタリング

インデックスを多くのチャンクに分割し、同じ知識空間に格納すると、検索効率が問題になる。例えば、ユーザが「浙江伊呉科技有限公司」の情報を求めるとき、他の会社の情報は思い出したくない。したがって、最初に会社名のメタデータ属性でフィルタリングできれば、効率と関連性が大幅に向上する。

async def aretrieve(
self, 
query: str, 
filters: Optional[MetadataFilters] = None
) -> List[Chunk]:
"""
Retrieve knowledge chunks.

Args:
query (str): async query text.
filters (Optional[MetadataFilters]): metadata filters.

Returns:
List[Chunk]: list of chunks
"""
return await self._aretrieve(query, filters)

 

(3) マルチ・ストラテジー・ハイブリッド・リコール
  • 優先度リコールに従って、さまざまなリトリーバーに優先順位を定義し、リトリーブされたらすぐにコンテンツを返す。
      • キューに書き込まれるqa_retrieverやdoc_tree_retrieverのような異なる検索を定義し、キューの先入れ先出し特性によって優先的な検索を実現する。
class RetrieverChain(BaseRetriever):
"""Retriever chain class."""

def __init__(
self,
retrievers: Optional[List[BaseRetriever]] = None,
executor: Optional[Executor] = None,
):
"""Create retriever chain instance."""
self._retrievers = retrievers or []
self._executor = executor or ThreadPoolExecutor()

async def retrieve(self, query: str, score_threshold: float, filters: Optional[dict] = None):
"""Perform retrieval with the given query, score threshold, and filters."""
for retriever in self._retrievers:
candidates_with_scores = await retriever.aretrieve_with_scores(
query=query, score_threshold=score_threshold, filters=filters
)

if candidates_with_scores:
return candidates_with_scores

 

  • 多知識インデックス/空間並列想起
      • 想起の完全性を確保するために、さまざまな知識の索引形式による並列想起によって候補リストを取得する。

(4) ポストフィルター

粗いスクリーニングの候補者リストを通過した後、細かいスクリーニングでどのようにノイズを濾過するのか?

  • 無関係な候補スライスの選別
      • 適時性拒否
      • ビジネス属性はカリングを満たさない
  • トップク・デデュープ
  • 並べ替え 粗いスクリーニングの想起だけでは不十分で、この時点で、検索結果の並べ替えを行うための戦略が必要である。例えば、組み合わせの関連性、マッチングなどの要素を再調整し、よりビジネスシナリオに沿った並べ替えを行うのである。このステップの後、LLMに結果を送り、最終的な処理を行うので、この部分の結果は非常に重要である。

     

    • オープンソースのモデルや、ビジネス・セマンティックの微調整が可能なモデルなど、関連する並べ替えモデルを使用したファイン・スクリーニング。
## Rerank model
# RERANK_MODEL = bce-reranker-base

#### If you do not set RERANK_MODEL_PATH, DB-GPT will read the model path from EMBEDDING_MODEL_CONFIG based on the RERANK_MODEL.
# RERANK_MODEL_PATH = /Users/chenketing/Desktop/project/DB-GPT-NEW/DB-GPT/models/bce-reranker-base_v1

#### The number of rerank results to return
# RERANK_TOP_K = 5

 

    • ビジネス RRF加重複合スコア カリング 異なる指標化されたリコールに基づく
score = 0.0

for q in queries:
if d in result(q):
score += 1.0 / (k + rank(result(q), d))

return score

# where:
# k is a ranking constant
# q is a query in the set of queries
# d is a document in the result set of q
# result(q) is the result set of q
# rank(result(q), d) is d's rank within the result(q) starting from 1

 

(5) ディスプレイの最適化 + 客引き / トピック・リーダーシップ
  • マークダウン書式を使ってモデルを出力させる
基于以下给出的已知信息,遵守规范约束,专业、简要回答用户的问题。

规范约束:
1. 如果已知信息包含的图片、链接、表格、代码块等特殊 markdown 标签格式的信息,确保在答案中包含原文这些图片、链接、表格和代码标签,不要丢弃不要修改,例如:
- 图片格式:`![image.png](xxx)`
- 链接格式:`[xxx](xxx)`
- 表格格式:`|xxx|xxx|xxx|`
- 代码格式:```xxx```。
2. 如果无法从提供的内容中获取答案,请说:“知识库中提供的内容不足以回答此问题”,禁止胡乱编造。
3. 回答的时候最好按照 1.2.3. 点进行总结,并以 Markdown 格式显示。

 

 2.2 動的知識RAGの最適化

ドキュメンテーションの知識は比較的静的であり、パーソナライズされた動的な情報に答えることはできない。

(1) ツール・アセット・ライブラリ

エンタープライズドメインのツール資産ライブラリを構築し、ツールAPI、様々なプラットフォームに散在するツールスクリプトを統合することで、インテリジェンスのエンドツーエンドの利用機能を提供する。例えば、静的知識ベースに加えて、ツールライブラリをインポートすることでツールを処理できる。

(2) ツール・リコール

ツール・リコールは、静的知識のためのRAGリコールの考え方に従ったものであり、ツール実行の結果を得るために、完全なツール実行ライフサイクルが使用される。

  • スロットの抽出:従来のnlpでLLMを取得し、一般的なビジネスタイプ、環境マーカー、ドメインモデルパラメーターなど、ユーザーの問題を解析する。
  • ツール選択:スタティックRAGに沿ったリコールで、ツール名リコールとツールパラメーターリコールという2つのメインレイヤーがある。
      • ツール・パラメーター・リコールは、TableRAGのアイデアと同様、最初にテーブル名をリコールし、次にフィールド名をリコールする。
  • パラメータ充填:スロットから抽出されたパラメータを、リコールのツールパラメータ定義に合わせる必要がある。
      • コードで入力することもできるし、モデルに入力させることもできる。
      • 最適化のアイデア:様々なプラットフォームツールの同じパラメータのパラメータ名は統一されておらず、ガバナンスに行くのは不便なので、まずドメインモデルデータ拡張のラウンドを実施することができ、全体のドメインモデルを取得した後、必要なパラメータが存在することを提案します。
  • パラメータ校正
      • 完全性チェック:パラメータ数の完全性チェックを行う。
      • パラメータ・ルール・チェック:パラメータ名の型、パラメータ値、列挙などのルール・チェックを行う。
  • パラメータ修正/調整、この部分は、主にユーザーとの対話の数を減らすために、ケースルール、列挙ルールなどを含む、ユーザーパラメータのエラー修正を自動完了することです。

 2.3 RAGレビュー

スマートQ&Aプロセスを評価する際には、想起関連性の精度とモデルQ&Aの関連性を別々に評価し、RAGプロセスの改善すべき点を特定するために、それらを合わせて検討する必要がある。

指標の評価:

EvaluationMetric
├── LLMEvaluationMetric
│ ├── AnswerRelevancyMetric
├── RetrieverEvaluationMetric
│ ├── RetrieverSimilarityMetric
│ ├── RetrieverMRRMetric
│ └── RetrieverHitRateMetric

 

  • RAGRetrieverEvaluationMetric:
      • RetrieverHitRateMetricヒット率はRAGを測定する。retriever検索結果の上位k個の文書に現れる想起の割合。
      • RetrieverMRRMetric:Mean Reciprocal Rank各クエリの精度は、検索結果における最も関連性の高い文書のランキングを分析することで算出される。具体的には、すべてのクエリに対する関連文書の逆順位の平均である。例えば、最も関連性の高い文書が1位であれば、その逆順位は1、2位であれば1/2、といった具合である。
      • RetrieverSimilarityMetric類似度メトリクスは、想起されたコンテンツと予測されたコンテンツとの類似度を計算するために計算される。

         

模型生成回答指標。

 

  • AnswerRelevancyMetricインテリジェントボディアンサーは、インテリジェントボディアンサーの回答がユーザーの質問にどの程度マッチするかによって、関連性を評価します。関連性の高い回答は、モデルがユーザーの質問を理解することを必要とするだけでなく、質問に密接に関連する回答を生成することも必要とします。これはユーザーの満足度とモデルの有用性に直接影響します。

 

  3.RAGランディング・ケース共有

1.データ・インフラ分野のRAG

 1.1 O&Mインテリジェンス機関の背景

データインフラストラクチャの分野では、毎日大量のアラートを受け取る運用 SRE が多いため、緊急事態への対応に多くの時間が費やされ、それがトラブルシューティングにつながり、さらにトラブルシューティングのレビューにつながり、それが経験につながる。また、ユーザーからの問い合わせに対応する時間もあり、ツールの使用に関する知識と経験を駆使して質問に答える必要がある。

 

そこで私たちは、データ・インフラストラクチャーのための一般的なインテリジェンスを構築することで、アラーム診断や質問への回答といったこれらの問題を解決したいと考えています。

 1.2 厳格かつ専門的なRAG

従来のRAG+エージェント技術は、汎用的で決定論的でないシングルステップのタスクシナリオを解決することができる。しかし、データインフラの分野で専門的なシナリオに直面した場合、検索プロセス全体が決定論的で専門的かつ現実的でなければならず、ステップバイステップの推論が必要となる。

右側は、NativeRAGによる一般化された要約である。これは、それほど多くのドメイン知識を持たないC-suiteユーザーにとっては有益な情報かもしれないが、専門家にとっては、この答えの部分はあまり意味をなさないだろう。

 

そこで、一般的なインテリジェンスとデータインフラストラクチャのインテリジェンスの違いをRAGで比較する:

  • 汎用インテリジェンス:従来のRAGは、それほど知的な厳密さや専門知識を必要とせず、カスタマーサービス、観光、プラットフォームのQ&Aボットなど、一部のビジネスシナリオに適している。
  • データ・インフラ・インテリジェンス本体:RAGプロセスは厳格で専門的であり、(警報→発見→止血→回復)を含むコンテキストを持つ専用のRAGワークフローと、階層関係を確立するために専門家によって促されたQ&Aと緊急対応経験の構造化された抽出を必要とする。そのため、私たちはナレッジグラフをデータベアラーとして選択しました。

 1.3 知識処理

データインフラの決定性と特異性に基づき、知識グラフを組み合わせて緊急対応経験を診断するための知識ベアラとして使用することを選択した。SREの緊急トラブルシューティングイベントの知識経験 緊急レビュープロセスと組み合わせることで、DB緊急イベントドリブンナレッジグラフを確立しました。DBジッターを例として、SQLが遅い問題、容量の問題など、DBジッターに影響を与えるいくつかのイベントを取り上げ、各緊急イベント間の関係を確立しました。

 

最後に、緊急事態のルールを正規化することで、複数のソースからの知識→知識の構造化抽出→緊急事態の関係抽出→専門家によるレビュー→知識の蓄積という段階的な標準化された知識処理システムを確立した。

 

 1.4 知識検索

インテリジェントボディ検索フェーズでは、静的知識検索の担い手としてGraphRAGを使用するため、DBジッタ異常を特定した後、DBジッタ異常ノードに関連するノードを分析の基礎として見つけます。各ノードには、知識抽出フェーズにおける各イベントのメタデータ情報(イベント名、イベント説明、関連ツール、ツールパラメータなど)も保持されています。

 

そのため、実行ツールの実行ライフサイクルリンクを通して、トラブルシューティングのための緊急診断の基礎として使用する動的データを得るために、リターン結果を得ることができる。この動的・静的ハイブリッド・リコール・アプローチにより、データ・インフラ・インテリジェンスの実行の確実性、専門性、厳密性は、純粋で単純なRAGリコールよりも保証される。

 1.5 AWEL + 代理店

最後に、コミュニティAWEL+AGENT技術を通じて、AGENTオーケストレーションのパラダイムは、意図→緊急診断専門家→診断根本原因分析専門家の専門家を作成するために使用されている。

 

各エージェントは異なる機能を持っています。 インテントエキスパートは、ユーザのインテントを特定し、解析し、アラートメッセージを特定する責任を持ちます。 診断エキスパートは、GraphRAGを通して分析する根本原因ノードを特定し、特定の根本原因情報を取得する必要があります。分析エキスパートは、各原因ノードのデータ+履歴分析レビューレポートを組み合わせて、診断分析レポートを作成する必要がある。

2.財務報告分析分野におけるRAG

最新の実践DB-GPTに基づく財務報告分析アシスタントを構築するには?

ナレッジアセット、ツールアセット、ナレッジグラフアセットなど、あなたのドメインに関連するドメインアセットのリポジトリを構築することができます。

  • ドメイン資産:ドメイン資産には、ナレッジベース、API、ツールスクリプトが含まれる。
  • 資産処理、資産データリンク全体には、ドメイン資産処理、ドメイン資産検索、ドメイン資産評価が含まれる。
      • 非構造化→構造化:構造化された方法で分類され、正しく整理された知識情報。
      • より豊かな意味情報を抽出する。
  • 資産の回収:
      • 願わくば、単一検索ではなく、階層化された優先順位検索であってほしい。
      • できれば、いくつかのルールのビジネス・セマンティクスを通して。
無断転載を禁じます:チーフAIシェアリングサークル " DB-GPTの実世界シナリオにおけるRAG最適化に関する10,000語の記事。
ja日本語