Галоўная / Артыкулы

Загрузка ў RAG з улікам якасці: маршрутызацыя дакументаў па чытэльнасці

Дэкларатыўны працэс docling-pipelines ацэньвае мову, дублікаты і чытэльнасць па Флешу, а потым адпраўляе дакументы ў два індэксы OpenSearch — для пошуку кліентаў і распрацоўшчыкаў.

Выдавец: REACTAPP.TOP8 хв чытання1893 слоў

Крыніцы: Architecting a Multi-Tier RAG Pipeline: Quality-Aware Document Routing with docling-pipelines

Пераклад базы знань падтрымкі кляўэнтаў у сістэму пошуку на асаблівай інтэлекты часта заканчываецца неудачаю ў той ж самай момант: кожны файл адносна аднакова обрабоўваецца. Рэалістычны корпус дакументаў — гэта сумешаннае зборы: ў яму ёсць апрантныя часта задаваемыя запытанні, структураваныя інструкцыі па продуктах, дакладныя мануалы для распрацоўшчыкаў, дубліруемыя юрыдычныя тэксты, а таксама калькулярныя файлы, у якіх немае чытальных слоў.

Калі усё гэта падаць у адну сістэму RAG для дыялогавання, якосьць адзысквання інформацыі падваічваецца. Кляўэнт, які хочаць простай інструкцыі, атрымвае фрагменты інжынерскага мануала. Адправка некальківатных тэкстаў чы сюжэтаў сістэмы дорогаму мадэлі для стварэння апрантнаў чы перакладу таксама ёст марнаваннем грошай.

Рашэння — распадзеліць дакументы па якосьці. У двухроўнай схеме кожны файл аналізуецца, выкарыстоўваюцься порожнія сторанкі, вылічваецца чытальнасць, а пасля корпус дакументаў дзеліцца:

  1. У рангу 1: пошук для спожыцеляў. Документы, якія лёгкая чытаемыя, атрымоўваюць структурныя метаданы, такія як колькасць слоў, каб падтрымаць дыялогавы пошук для кліянтаў.
  2. У рангу 2: пошук для распрацоўшчыкаў і дыяведчых цыяляў. Інтэнсіўны тэхнічны матэрыял прабывае ў сваёй сабе індэксе для складных тэхнічных запытанняў.

docling-pipelines робіць гэта практычным. Цэў адкрыты код, ліцензаваны па стандарту MIT, падтрымваны IBM, які стварае і запускае графы апрацоўкі дакументаў непасрэдна з конфігурацыі у фармаце JSON. Не трэба спецыяльных інструментаў на Python, таму што аператары перадаюць дакументы аднам другаму у вачыннай памяці як табелі Apache Arrow, так што проміжныя ператворэнні і пераказы коштаюць майжэ нічога з точкі зору CPU і памяці.

Форма пайплайна

Усё знаходзіцца ў аднам файле з данымі у фармаце JSON, які опісвае направлены ацыклічны граф:

  1. ingest чытае файлы PDF, TXT, DOCX і HTML з дыска.
  2. extract выкарыстоўвае бібліятэку Docling для выявлення структураванага тэксту.
  3. detect_language выявляе мову кожнага дакумента.
  4. dedup выкарыстоўвае хэшы кантэнту, ўбачліваючы дублікатныя рэкі.
  5. doc_quality вылічае структурныя паказнікі, такія як загальная колькасць слоў.
  6. readability вылічае рэйтынгі складнасці тэксту.
  7. quality_branching выбірае шлях на аднойчыні з рэйтынгам Flesch Reading Ease: калі рэйтынг вышы ў 60, то дакумент патрапляе у калектыў высокай якосці, а якшо 60 або меней — у калектыў нізкай якосці.
  • Для вісокоякісного шляху вікорыстовуюцца ml_enrichment_high_quality, embeddings_high_quality і vectordb_high_quality. Ён додае мовні ознакі, засновані на штучному інтэлекты, створуе векторні ембеддынгі і запісуе іх у індэкс high_quality_docs.
  • Для нізькоякісного шляху вікорыстовуюцца sql_filter_low_quality, embeddings_low_quality і vectordb_low_quality. Ён відаляе порожні радкі, ембеддуе залішок даных і запісуе іх у low_quality_docs.
  • Аналіз перад роздыленням

    Кожны дакумент патрэбуе профіль, прытымкі якога ён можа быць направлены. Пасля таго, як ingest чытае даны дакумента, а extract ператварае ўзорку на тэкст, кожны наступны прыемнік працуе як трансфармер: ён аналізуе табліцу і дадае новыя столбцы ў тую ж табліцу Arrow у памяці. Спачатку выконваюцца простыя пераконтроўкі, якія выконваюцца толькі за дапамогою CPU: вялікасць мовы, наявнасць дуплікатав і складнасць тэксту.

    Адгукаванне мовы

    Пасля таго, як мова адгукавана, патрэбныя мадэлі машыннага навчання і формулы для адрыснай чытаемасці, таму спачатку выконваецца адгукаванне.

    {
          "name": "detect_language",
          "type": "lang_detect",
          "config": {
            "doc_column": "content"
          },
          "depends_on": [
            "extract"
          ]
        }
    

    Апаратчык чытае столбец content і дадае да яго lang_name (код ISO 639-1) і lang_score. Размешчэнне іх адразу пасля выкарыстоўвання значыць, што кожны наступны элемент, які залежыць ад мовы, можа выкарыстоўваць ўсе гэтыя даны.

    Усуненне дуплікатаў

    Дуплікатныя дакументы спамошчуюць вырахункі і пашкоджаюць рэзультаты пошуку.

    {
          "name": "dedup",
          "type": "ededup",
          "config": {
            "doc_column": "content",
            "doc_id_column": "doc_id_hash"
          },
          "depends_on": [
            "detect_language"
          ]
        }
    

    Ён адначас прызнаецца да хэша контэнту, які зберагаецца ў doc_id_hash, і да неасобліванага тэксту ў content, пасля чаго адмахвае павтараючыяся радкі з таблыцы. Такое раннее выкарыстоўванне дапамагае уберагчы пасляэйшыя крокі ад непатрэбной працы.

    Якасць дакумента

    Базовыя структурныя пераканальванні выкрываюць порожнія сторынкі і нерэгулярныя макеты.

    {
          "name": "doc_quality",
          "type": "doc_quality",
          "config": {
            "doc_column": "content",
            "doc_content_column": "content",
            "text_lang": "en"
          },
          "depends_on": [
            "dedup"
          ]
        }
    

    Гэта дадзе 11 структурных столбцоў, усія пазначаны docq_. Найважлівейшы з іх — docq_total_words, яны паказвае загальную колькасць слоў у кожным дакуменце.

    Чытаемасць

    Формулы для адліквідаціі чытаемасці ацэнююць ступень складнасці на адважанні дужыны слоў, складоў і структуры рэчэння.

    {
          "name": "readability",
          "type": "readability",
          "config": {
            "doc_column": "content",
            "readability_score_list": [
              "flesch_reading_ease",
              "flesch_kincaid_grade",
              "gunning_fog",
              "difficult_words",
              "dale_chall_readability_score"
            ]
          },
          "depends_on": [
            "doc_quality"
          ]
        }
    

    Масавэц readability_score_list паведамляе аператару, якія паказнікі трэба вылічыць і дадзіць як столбцы. Рутаванне завісіць ад рэйтынгу Flesch Reading Ease, які колічыцца ад 0 да 100:

    • Значэнне вышэй 60 означае просты, доступны язык, прыдатны для шырокай аўдыторыі центра дапамогі.
    • Значэнне 60 або меней означае насыцёны, тэхнічны стыль, які выказвае патрэбу ў спецыяльных знаннях.

    Этап розгалужэння

    Аператар розгалужэння дзеліць набор дадзеных Arrow на адзінаковыя шляхі апрацоўкі.

    {
          "name": "quality_branching",
          "type": "branching",
          "config": {
            "branches": {
              "high_quality_branch": {
                "link_name": "High Quality Documents",
                "criteria_json": {
                  "criteria_list": [
                    {
                      "variable": "flesch_reading_ease",
                      "operator": ">",
                      "value": 60
                    }
                  ],
                  "logical_operator": "AND"
                }
              },
              "low_quality_branch": {
                "link_name": "Low Quality Documents",
                "criteria_json": {
                  "criteria_list": [
                    {
                      "variable": "flesch_reading_ease",
                      "operator": "<=",
                      "value": 60
                    }
                  ],
                  "logical_operator": "AND"
                }
              }
            }
          },
          "depends_on": [
            "readability"
          ]
        }
    

    Маршрутацыя кантролюецца дэкларатывным блакам criteria_json, які складаецца з чатырох поль:

    • variable — гэта назва столбца, які трэба пераканаліць, напрыклад flesch_reading_ease.
    • operator — гэта знак пораўнення, такі як > або <=.
    • value — гэта праг, у даным случае 60.
    • logical_operator — гэта з’едыненне калькіляў за дапамою AND або OR.

    Калі правілам ёсць flesch_reading_ease > 60, двайнік атрыбутыўна пераканалівае калькіляў, дзеліць таблыцу ў памяці і запускае кожную з наступных гілак.

    Высокая якосць траекторыі: адзагледжэнне, уключэнне, індэксаванне

    Дакументы, якія надаюцца праз high_quality_branch, спачатку праходзяць працэс адзагледжэння за дапамою тэхналогій машыннага навучэння.

    {
          "name": "ml_enrichment_high_quality",
          "type": "ml_enrichment",
          "config": {
            "doc_column": "content",
            "lang_column": "lang_name",
            "output_column_prefix": "ml_",
            "error_column_name": "enrichment_error"
          },
          "depends_on": [
            "quality_branching.high_quality_branch"
          ]
        }
    

    ml_enrichment аналізуе тэкст за дапамою модэляў, якія разумеюць мову, і стварае метаданы, такія як колькасць рэчэй, характарыстыкі слоў і спісы іменаў, усе гэта прызначана для лепшага аднаходжэння інфармацыі. Ён залежыць ад столбца lang_name з кроку выканаўлення дытэкціі. Паколькі гэта ўжо частка працэсу, якая сільна навантажвае CPU, ён працуе толькі з тэкстам, які можна прачытаць. Настройка output_column_prefix дадае новым столбцам прэфікс ml_, уключаючы ml_num_words.

    Далей тэкст ператвараецца на 2560-вымерныя эмбедынгі. Модэль — openai/granite4:latest, які выдаеўцем являецца локальны сервер Ollama праз LiteLLM:

    {
          "name": "embeddings_high_quality",
          "type": "embeddings",
          "config": {
            "embeddings_column": "embeddings",
            "overlap_ratio": 0.2,
            "doc_column": "content",
            "provider_config": {
              "api_base": "http://localhost:11434/v1",
              "api_key": "${OLLAMA_API_KEY}",
              "model_id": "openai/granite4:latest"
            },
            "provider": "litellm"
          },
          "depends_on": [
            "ml_enrichment_high_quality"
          ]
        }
    

    Пашчэ, дакументы індэксуюцца ў OpenSearch, пры чым feature_mappings сувязуюць столбцы Arrow з полямі OpenSearch:

    {
          "name": "vectordb_high_quality",
          "type": "vectordb",
          "config": {
            "provider": "opensearch",
            "doc_id_column": "doc_id_hash",
            "embeddings_column": "embeddings",
            "vector_dimension": 2560,
            "create_index": "true",
            "provider_config": {
              "index_name": "high_quality_docs",
              "host": "localhost",
              "port": 9200,
              "username": "${OPENSEARCH_USERNAME}",
              "password": "${OPENSEARCH_PASSWORD}",
              "use_ssl": false,
              "verify_certs": false,
              "batch_size": 100,
              "engine": "faiss",
              "algorithm": "hnsw",
              "space_type": "l2"
            },
            "feature_mappings": [
              {"feature_name": "doc_id_hash", "mapped_column_name": "pk"},
              {"feature_name": "name", "mapped_column_name": "doc_name"},
              {"feature_name": "content", "mapped_column_name": "text"},
              {"feature_name": "embeddings", "mapped_column_name": "vector_embeddings"},
              {"feature_name": "lang_name", "mapped_column_name": "language"},
              {"feature_name": "flesch_reading_ease", "mapped_column_name": "readability_score"},
              {"feature_name": "ml_num_words", "mapped_column_name": "word_count"}
            ]
          },
          "depends_on": [
            "embeddings_high_quality"
          ]
        }
    

    Нявысакасцей якосці шлях: фільтрацыя, уключэнне, індэксаванне

    Дакументы на low_quality_branch прахоцяюць дорогі крок ml_enrichment. Дзеяны з іх пасля выкарыстоўвання можа не мець чытальных слоў, напрыклад, у зв’язку з парадуранымі файламі аб порожнімі сканамі, і уключэнне порожняй строкі толькі дадае шуму у вектарным прасторы. Фільтр ўсуне іх:

    {
          "name": "sql_filter_low_quality",
          "type": "sql_filter",
          "config": {
            "criteria_json": {
              "criteria_list": [
                {
                  "variable": "docq_total_words",
                  "operator": ">",
                  "value": 0
                }
              ],
              "logical_operator": "AND"
            }
          },
          "depends_on": [
            "quality_branching.low_quality_branch"
          ]
        }
    

    Фільтр пераглядае столбець docq_total_words з модуля doc_quality і адзяўляе будзь-кі дакументы, у якіх колькасць слоў равная нулю.

    Тые дакументы, якія застаюцца, большасцю тэхнічныя матэрыялы, прадаўляюцца з адным і тым жа модэлем granite4 і зберагаюцца ў аднародным індэксе OpenSearch:

    {
          "name": "vectordb_low_quality",
          "type": "vectordb",
          "config": {
            "provider": "opensearch",
            "doc_id_column": "doc_id_hash",
            "embeddings_column": "embeddings",
            "vector_dimension": 2560,
            "create_index": "true",
            "provider_config": {
              "index_name": "low_quality_docs",
              "host": "localhost",
              "port": 9200,
              "username": "${OPENSEARCH_USERNAME}",
              "password": "${OPENSEARCH_PASSWORD}",
              "use_ssl": false,
              "verify_certs": false,
              "batch_size": 100,
              "engine": "faiss",
              "algorithm": "hnsw",
              "space_type": "l2"
            },
            "feature_mappings": [
              {"feature_name": "doc_id_hash", "mapped_column_name": "pk"},
              {"feature_name": "name", "mapped_column_name": "doc_name"},
              {"feature_name": "content", "mapped_column_name": "text"},
              {"feature_name": "embeddings", "mapped_column_name": "vector_embeddings"},
              {"feature_name": "lang_name", "mapped_column_name": "language"},
              {"feature_name": "flesch_reading_ease", "mapped_column_name": "readability_score"},
              {"feature_name": "difficult_words", "mapped_column_name": "difficult_words"}
            ]
          },
          "depends_on": [
            "embeddings_low_quality"
          ]
        }
    

    Паколькі галузь адзінчылася без процэса абгрунтавання, для гэтых дакументаў не існуе word_count. У замен выкарыстоўваецца расчыслены кантэкст difficult_words, што дапамагае пад час тэхнічных запытанняў.

    Два індэксы, два стылі запытанняў

    Адзінаковыя індэксы па рывень вочымасці дазволяюць разным аўдыторыям выконваць пошук на розны лад.

    Пошук у цэнтры дапамогі

    Для канечных корыстнікаў запыт падае на high_quality_docs. У ям утрымваюцца толькі лёгкія для чытання інструкцыі (readability_score > 60) з рэальным зместам (word_count > 100):

    curl -XGET "http://localhost:9200/high_quality_docs/_search" \
      -H 'Content-Type: application/json' -d'
    {
      "query": {
        "bool": {
          "must": [
            {
              "knn": {
                "vector_embeddings": {
                  "vector": [0.015, -0.023, 0.004],
                  "k": 10
                }
              }
            }
          ],
          "filter": [
            {
              "range": {
                "readability_score": {
                  "gt": 60
                }
              }
            },
            {
              "range": {
                "word_count": {
                  "gt": 100
                }
              }
            }
          ]
        }
      }
    }'
    

    Пошук параграфаў для распрацоўшчыкаў

    Для экспертных корыстнікаў, якія шукаюць тэхнічныя характарыстыкі, запіт нацэлёваны на low_quality_docs. Ён аналізуе складны матэрыял і заставляе ў спісе тыя фрагменты, якія маюць больш за 5 складных тэхнічных тэрмінаў (difficult_words > 5):

    curl -XGET "http://localhost:9200/low_quality_docs/_search" \
      -H 'Content-Type: application/json' -d'
    {
      "query": {
        "bool": {
          "must": [
            {
              "knn": {
                "vector_embeddings": {
                  "vector": [0.015, -0.023, 0.004],
                  "k": 10
                }
              }
            }
          ],
          "filter": [
            {
              "range": {
                "difficult_words": {
                  "gt": 5
                }
              }
            }
          ]
        }
      }
    }'
    

    Запуск програмі

    У рэпазітарыі ёсць скрыпт налаштавання, які стварае віртуальную срэду, інсталюе неабяцковыя компоненты, запускае локальныя кантэйнеры OpenSearch і рэгіструе мадэлі Ollama.

    Крок 1: налаштавання асяроддзя

    Клонуйце рэпазітары і запускайце скрыпт:

    git clone https://github.com/IBM/docling-pipelines.git
    cd docling-pipelines
    ./scripts/setup_docling_pipelines_environment.sh
    

    Або запусціце яго безпосерэдна з PyPI:

    pip install docling-pipelines
    

    Крок 2: настаўленне зменных сяродавішча

    export OLLAMA_API_KEY=ollama
    export OPENSEARCH_USERNAME=admin
    export OPENSEARCH_PASSWORD=<your-password>
    

    Шаг 3: запуск працэсу

    Запусціце пайплайн з лінійкі каманд:

    docling-pipelines --flow-file sample_flows/advanced/branching_quality_routing.json
    

    Што выведае запуск

    Рэзультат паказвае ход выканання, пры чым фіксуецца кожная трансформацыя і рашэнне па маршруце:

    $ docling-pipelines --flow-file sample_flows/advanced/branching_quality_routing.json
    [INFO] [ingest] Loading files from tests/fixtures/customer_support_docs/
    [INFO] [ingest] Ingested 12 files.
    [INFO] [extract] Running extract_operator using docling_library...
    [INFO] [extract] Extracted text from 12 documents.
    [INFO] [detect_language] Running lang_detect...
    [INFO] [detect_language] Complete. lang_name assigned.
    [INFO] [dedup] Running ededup...
    [INFO] [dedup] Removed 2 duplicate documents. 10 documents remaining.
    [INFO] [doc_quality] Running doc_quality...
    [INFO] [doc_quality] Computed docq_* features for 10 documents.
    [INFO] [readability] Running readability...
    [INFO] [readability] Computed readability features for 10 documents.
    [INFO] [quality_branching] Branching 10 documents...
    [INFO] [quality_branching] Routed 6 documents to link 'High Quality Documents' (flesch_reading_ease > 60).
    [INFO] [quality_branching] Routed 4 documents to link 'Low Quality Documents' (flesch_reading_ease <= 60).
    [INFO] [ml_enrichment_high_quality] Running ml_enrichment on 6 documents...
    [INFO] [embeddings_high_quality] Generating embeddings with model 'openai/granite4:latest'...
    [INFO] [vectordb_high_quality] Uploaded 6 documents to OpenSearch index 'high_quality_docs'.
    [INFO] [sql_filter_low_quality] Running sql_filter on 4 documents...
    [INFO] [sql_filter_low_quality] Filtered out 0 empty documents. 4 documents remaining.
    [INFO] [embeddings_low_quality] Generating embeddings with model 'openai/granite4:latest'...
    [INFO] [vectordb_low_quality] Uploaded 4 documents to OpenSearch index 'low_quality_docs'.
    [INFO] Flow execution finished successfully in 4.23s.
    

    Перанесенне памятакаў прыроды якасці і правіла маршрутацыі з спецыяльнага коду на Python у фармат дэкларатывных налашчэнняяў робіць працэс прыемкі дадзеных быстрым і лёгкім у адтрыманні. Косц працэў завісіць ад значэння дакумента, а прыкладнае рашэнне RAG отрымае чыстыя, адпрацаваныя індэксы для кожной аўдытарыі.

    Ідэя розгалужэння працуе з будзь-ямі памяткамі, вылічанымі раней у працэсе. Можна зменіць крэтырыя маршрутацыі на адпаведнасць мове, рэйтынгу рызыку ПІІ чыста спецыяльнай меткі класыфікатора. Пакалі логіка пайплайна застаецца аддзеленай ад коду керавання, команды можаюць расшырваць пайплайн без збільшэння навантажэння на адтрыманне.