Главная / Статьи / Практические заметки: За пределами базового RAG: создание системы юридических исследований в производственном стиле

Практические заметки: За пределами базового RAG: создание системы юридических исследований в производственном стиле

Пошаговое руководство по практическим заметкам: за пределами базового RAG: создание системы юридических исследований в производственном стиле: контракты, проверки и готовые блоки кода для команд, использующих эту модель.

3979 слов

В этом руководстве описывается процесс создания рабочей системы от сырьевых материалов до готового решения для проекта «Beyond Basic RAG: Building a Production-Style Legal Research Assistant (Part-I)». Основное внимание уделяется практическим шагам, четким проверкам и коду, который можно просто добавить в репозиторий без необходимости угадывать его назначение. На этапе обзора необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не пытаясь угадать скрытое состояние системы. Необходимо одновременно задокументировать успешный сценарий работы и сценарий восстановления. Повторные попытки, проверки человеком и обработка ошибок являются неотъемлемой частью продукта, а не элементами, добавляемыми позже.

1. Прием данных: преобразование юридического PDF в структурированный контент

При работе над этапом обработки данных сначала запишите спецификацию: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой чек-лист поможет сохранять честность при последующих изменениях кода. Предпочитайте небольшие, тестируемые модули большим скриптам. Когда какой-то шаг терпит неудачу, ошибка должна указывать на конкретную проблему, а не на сложную структуру обработки данных. Оцените уровень воспроизводимости ответов на фиксированном наборе вопросов перед настройкой подсказок. Частая смена подсказок редко помогает улучшить качество поиска.

!mineru -p c.pdf -o output --dump-content-list -b pipeline -l en

2. Разбиение на части

При работе над вторым этапом разбиения на части сначала запишите контракт: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия элементам, определите критерии успешности и не допускайте молчаливого частичного выполнения задачи. Оцените уровень воспроизведения на фиксированном наборе вопросов перед настройкой подсказок. Частая смена подсказок редко помогает улучшить качество поиска.

Structured document
        ↓
Heading-aware parent chunks
        ↓
Semantic child chunks

Почему двухуровневая стратегия полезна

При работе над этапом стратегии двух уровней «Почему» сначала запишите условия работы: необходимые входные данные, сигнал успеха и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Рядом с функциональными результатами задокументируйте время выполнения и стоимость токенов или запросов. Очевидность затрат с самого начала предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды. Перед настройкой подсказок измерьте точность воспроизведения ответов на фиксированный набор вопросов. Частая смена подсказок редко помогает улучшить качество поиска. При работе над этапом стратегии двух уровней «Почему» сначала запишите условия работы: необходимые входные данные, сигнал успеха и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Одновременно задокументируйте успешный сценарий работы и сценарий восстановления. Повторные попытки, проверка человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки.

Query
  ↓
Retrieve focused child
  ↓
Read parent_id
  ↓
Return complete parent context

Создание родительских блоков с учётом заголовков

Этап создания родительских блоков с учётом заголовков работает наилучшим образом, если рассматривать его как измеримую составляющую. Соберите один идеальный пример транскрипции, один пример сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работы. Предпочитайте небольшие, тестируемые единицы вместо обширных скриптов. Когда какой-либо шаг срабатывает некорректно, причина сбоя должна указывать на конкретную ответственность, а не на запутанную цепочку операций. Разделяйте политику формирования блоков и политику извлечения данных. Изменение одной из них не должно приводить к переписыванию другой при изменении показателей качества.

data/processed/cr.md
data/extracted/auto/blockpage.json
code/chunking_parent.py

Шаг 1: Прочитайте оба результата извлечения

Шаг 1: Чтение обоих этапных документов наиболее эффективно при рассмотрении их как измеримой поверхности. Зафиксируйте один идеальный пример выполнения, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работы. Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Дайте названия создаваемым документам, определите критерии успешного выполнения и не соглашайтесь на молчаливое частичное завершение работы. Разделяйте политику разбиения на части и политику извлечения данных. Изменение одной из них не должно приводить к переписыванию другой при изменении показателей качества.

md_text = MARKDOWN_PATH.read_text(encoding="utf-8")
with BLOCKPAGE_PATH.open("r", encoding="utf-8") as file:
    blockpage = json.load(file)

Шаг 2: Разделение Markdown на блоки

Шаг 2: Разделение этапа работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Записывайте временные показатели, а также стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные счёты при переходе от демо-среды к общедоступным средам. Разделяйте политику разбиения на части и политику поиска данных. Изменение одной из них не должно приводить к необходимости переписывания другой при изменении показателей качества. Шаг 2: Разделение этапа работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Документируйте одновременно успешный путь выполнения и путь восстановления. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не элементами последующей доработки.

for raw_block in md_text.split("\n\n"):
heading
paragraph
list
table
superscript
blank
HEADING_RE = re.compile(r"^(#{1,6})\s+")

Шаг 3: Отслеживание активного заголовка

На третьем этапе необходимо определить стадию выполнения, входные данные, ответственного за шаг и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Лучше использовать небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага причина должна быть связана с конкретной функцией, а не с запутанной цепочкой операций. Указывайте те фрагменты текста, на которых основан ответ. Без цитат операторы не смогут отличить вымысел от проблем с индексацией.

def find_heading(heading_text: str):
    nonlocal search_pos
    for index in range(search_pos, len(blockpage)):
        block = blockpage[index]        if (
            block.get("type") == "text"
            and block.get("text") == heading_text
            and "text_level" in block
        ):
            search_pos = index + 1
            return block

Шаг 4: Сбор связанного контента

На этапе 4 «Сбор связанных данных» необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг, исходя из известной точки контроля, без необходимости угадывания скрытого состояния. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Укажите названия создаваемых файлов, определите критерии успеха и не допускайте молчаливого частичного завершения работы. Цитируйте те фрагменты, которые легли в основу ответа. Без цитат операторы не смогут отличить галлюцинации от пробелов в индексации.

Heading
  ├── Paragraph
  ├── Clause
  ├── List
  └── Table
        ↓
     Parent chunk

Шаг 5: Присвоение стабильных метаданных

На этапе 5 «Назначение стабильной фазы» необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Записывайте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Отображение стоимости заранее предотвращает неожиданные счета при переходе с демо-среды в общедоступные среды. Указывайте конкретные фрагменты текста, на которых основан ответ. Без цитат операторы не смогут отличить галлюцинации от пробелов в индексации. На этапе 5 «Назначение стабильной фазы» необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Документируйте одновременно «идеальный путь» и пути восстановления. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не элементами последующей доработки.

{
    "parent_id": f"parent_{len(chunks):04d}",
    "doc_id": DOC_ID,
    "heading_path": heading_path.copy(),
    "text": "\n\n".join(stack),
}
{
  "parent_id": "parent_0164",
  "doc_id": "constitution_of_india",
  "heading_path": ["PART XII"],
  "text": "# PART XII\n\nFINANCE, PROPERTY, CONTRACTS AND SUITS..."
}
PART XII — Finance
Article 264 — Interpretation
Article 265 — Taxes not to be imposed without authority of law
Article 266 — Consolidated Funds and public accounts
Article 267 — Contingency Fund

Создание семантических дочерних блоков

На этапе создания семантических дочерних блоков сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и последствия частичной неудачи. Такой список поможет сохранять честность при последующих изменениях кода. Лучше использовать небольшие, тестируемые единицы вместо обширных скриптов. Если какой-то шаг не сработает, причина должна быть связана с конкретной функцией, а не с запутанной цепочкой операций. Перед настройкой подсказок измерьте уровень воспроизведения ответов на фиксированном наборе вопросов. Частая смена подсказок редко помогает улучшить качество поиска.

code/semantic-children.ipynb

Шаг 1: Разбиение родительского элемента на структурные блоки

При работе над этапом «1. Анализ» сначала запишите условия контракта: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой чек-лист поможет избежать ошибок при последующих изменениях кода. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия элементам, определите критерии успешности и не допускайте молчаливого частичного выполнения задачи. Оцените уровень воспроизводимости на фиксированном наборе вопросов перед настройкой подсказок. Частая смена подсказок редко помогает улучшить качество поиска.

table_pattern = re.compile(
    r"(<table[\s\S]*?</table>)",
    re.IGNORECASE
)

Шаг 2: Привязка заголовков к их содержимому

При работе над этапом Шаг 2 «Добавление заголовков» сначала запишите условия работы системы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Запишите также время выполнения операций и стоимость токенов или запросов рядом с результатами работы. Очевидность затрат с самого начала предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам. Перед настройкой подсказок измерьте точность воспроизведения ответов на фиксированный набор вопросов. Частая смена подсказок редко помогает улучшить качество поиска. При работе над этапом Шаг 2 «Добавление заголовков» сначала запишите условия работы системы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Одновременно задокументируйте успешный и восстановительный сценарии работы. Повторные попытки, проверка человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки.

if pending_heading:
    block.text = pending_heading + "\n\n" + block.text
    pending_heading = None

Шаг 3: Сравнение соседних абзацев

Наиболее эффективно шаг 3 сравнения соседних элементов работает, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работы. Предпочитайте небольшие, тестируемые единицы вместо обширных скриптов. При сбое какого-либо шага причина должна указывать на конкретную ответственность, а не на запутанную цепочку операций. Разделяйте политику разбиения на части и политику извлечения данных. Изменение одной из них не должно приводить к переписыванию другой при изменении показателей качества.

embedder = SentenceTransformer(
    "BAAI/bge-base-en-v1.5"
)
similarity = cosine_similarity(
    emb1,
    emb2
)[0][0]
Similarity threshold: 0.40

Шаг 4: Применение ограничений по размеру и структуре

Этап 4 «Применение размера» работает наилучшим образом, если рассматривать его как измеримую поверхность. Соберите один образец успешного результата, один пример сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работы. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия создаваемым элементам, определите критерии успеха и не соглашайтесь на молчаливое частичное выполнение задачи. Разделяйте политику разбиения на части и политику извлечения данных. Изменение одной из них не должно приводить к переписыванию другой при изменении показателей качества.

Preferred minimum size: 800 characters
Maximum combined size: 1,600 characters
Tiny-block threshold: 150 characters
if (
    current_type == BlockType.TABLE
    and block.type != BlockType.TABLE
) or (
    block.type == BlockType.TABLE
    and current_type != BlockType.TABLE
):
    is_under_min = False
Document structure
        +
Semantic similarity
        +
Minimum and maximum sizes

Этап 5: Сохранение родительских связей

Шаг 5 «Сохранение этапа» работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Записывайте временные показатели, а также стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные счёты при переходе от демо-среды к общедоступным средам. Разделяйте политику разбиения данных на части и политику их извлечения; изменение одной не должно принуждать к переписыванию другой при изменении показателей качества. Шаг 5 «Сохранение этапа» работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Документируйте одновременно успешный путь выполнения и путь восстановления. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не этапом последующей доработки.

{
    "parent_id": parent["parent_id"],
    "child_id": f"{parent['parent_id']}_child_{index}",
    "doc_id": parent.get("doc_id", ""),
    "heading_path": parent.get("heading_path", []),
    "text": chunk["text"],
    "type": chunk.get("type", "mixed"),
    "embedding": encode_text(chunk["text"])
}
parent_0164
│
├── parent_0164_child_1
│   Article 264 and introductory Finance context
│
├── parent_0164_child_2
│   Articles 265 and 266 concerning taxation and public funds
│
└── parent_0164_child_3
    Article 267 concerning the Contingency Fund
{
  "parent_id": "parent_0164"
}
{
  "child_id": "parent_0164_child_2",
  "parent_id": "parent_0164",
  "doc_id": "constitution_of_india",
  "heading_path": ["PART XII"],
  "type": "list",
  "text": "265. Taxes not to be imposed save by authority of law...",
  "embedding": [0.012, -0.034, 0.021]
}

3. Гибридный поиск: от запроса к родительскому контексту

При использовании гибридного метода поиска на третьем этапе необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг, исходя из известной точки контроля, без необходимости угадывать скрытое состояние. Лучше использовать небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага причина должна быть связана с конкретной функцией, а не с запутанной структурой обработки данных. Указывайте те части текста, которые легли в основу ответа. Без цитат операторы не смогут отличить галлюцинации от пробелов в индексации.

Почему одного метода поиска было недостаточно

На этапе поиска причин необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Укажите названия элементов, определите критерии успеха и не допускайте молчаливого частичного выполнения. Цитируйте те фрагменты, которые на самом деле легли в основу ответа. Без цитат операторы не смогут отличить галлюцинации от пробелов в индексации.

Редкий поиск с использованием BM25

Для этапа разреженного поиска с использованием алгоритма BM25 необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии системы. Необходимо фиксировать время выполнения операций, а также стоимость обработки токенов или запросов наряду с функциональными результатами. Отображение стоимости на ранних этапах предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам. Следует указывать конкретные фрагменты текста, на которых основан ответ. Без указания источников операторы не могут отличить галлюцинации от пробелов в индексации. Для этапа разреженного поиска с использованием алгоритма BM25 необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии системы. Необходимо одновременно задокументировать успешный сценарий выполнения и сценарии восстановления работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не этапами последующей доработки.

При работе над этапом плотного поиска с использованием BGE сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и что происходит при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Предпочитайте небольшие, тестируемые модули вместо обширных скриптов. Если какой-то шаг не сработает, причина неудачи должна указывать на конкретную ответственность, а не на запутанную цепочку операций. Измеряйте показатель воспроизведения на фиксированном наборе вопросов перед настройкой подсказок — частая смена подсказок редко помогает улучшить качество поиска.

embedding_text = heading_path + child_text

Выбор модели вкладки через оценку

При работе над этапом выбора модели эмбеддингов сначала запишите контракт: необходимые входные данные, сигнал о успешном выполнении и что происходит при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия элементам, определите критерии успешности и не допускайте молчаливого частичного завершения работы. Храните в кэше стабильные системные инструкции и схемы инструментов. Пересылка одинаковых данных является распространенной причиной избыточных ресурсов.

query_text = (
    "Represent this sentence for searching relevant passages: "
    + user_query
)

Создание индекса FAISS

При работе над этапом создания индекса FAISS сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Записывайте время выполнения и стоимость обработки токенов или запросов рядом с функциональными результатами. Очевидность затрат с самого начала предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды. Измеряйте показатель воспроизводимости на фиксированном наборе вопросов перед настройкой подсказок. Частая смена подсказок редко помогает улучшить качество поиска. При работе над этапом создания индекса FAISS сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Документируйте одновременно успешный и восстановительный сценарии работы. Повторные попытки, проверка человеком и обработка неработающих сообщений являются частью продукта, а не элементами последующей доработки.

index = faiss.IndexHNSWFlat(
    embedding_dimension,
    32,
    faiss.METRIC_INNER_PRODUCT,
)
index.hnsw.efConstruction = 200
index.hnsw.efSearch = 64
index.add(embeddings)

Сочетание обоих рейтингов

Этап сочетания обоих рейтингов работает наилучшим образом, если его рассматривать как измеримую структуру. Соберите один идеальный пример, один пример сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Предпочитайте небольшие, тестируемые единицы вместо обширных скриптов. Когда какой-либо шаг срабатывает некорректно, причина сбоя должна указывать на конкретную ответственность, а не на запутанную цепочку операций. Разделяйте политику разбиения на части и политику поиска данных. Изменение одной из них не должно приводить к переписыванию другой при изменении показателей качества.

RRF score = Σ 1 / (k + rank + 1)
sparse_results = bm25_search(query)
dense_results = dense_search(query)
fused_candidates = reciprocal_rank_fusion(
    sparse_results,
    dense_results,
)

Переоценка с использованием кросс-кодера

Метод переранкинга с использованием этапа кросс-кодера работает наилучшим образом, если рассматривать его как измеримую структуру. Соберите один идеальный пример, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия соответствующим элементам, определите критерии успеха и не соглашайтесь на молчаливое частичное выполнение задачи. Разделяйте политику разбиения на части и политику поиска данных. Изменение одной из них не должно приводить к переписыванию другой при изменении показателей качества.

pairs = [
    (query, child_text),
    ...
]
scores = reranker.predict(pairs)
candidates = fused_candidates[:30]
reranked_children = cross_encoder.rank(query, candidates)
selected_children = [
    child
    for child in reranked_children[:20]
    if child.score >= 0.30
]

Расширение выбранных дочерних элементов в контекст родителя

Процесс расширения выбранных дочерних элементов на этап тестирования работает наилучшим образом, когда его рассматривают как измеримую величину. Перед расширением объема работы необходимо зафиксировать один идеальный пример выполнения, один случай сбоя и записку о возврате к предыдущему состоянию. Регистрируйте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Отображение стоимости на раннем этапе предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам. Разделяйте политику разбиения данных на части и политику их поиска. Изменение одной из них не должно принуждать к переписыванию другой при изменении показателей качества. Процесс расширения выбранных дочерних элементов на этап тестирования работает наилучшим образом, когда его рассматривают как измеримую величину. Перед расширением объема работы необходимо зафиксировать один идеальный пример выполнения, один случай сбоя и записку о возврате к предыдущему состоянию. Документируйте одновременно успешный путь выполнения и путь восстановления. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не этапом последующей доработки.

{
  "child_id": "parent_0082_child_1",
  "parent_id": "parent_0082",
  "text": "23. Prohibition of traffic in human beings and forced labour..."
}
parent_id = selected_child["parent_id"]
parent = parent_lookup[parent_id]
Selected child 1 ──┐
Selected child 2 ──┼── parent_0082
Selected child 3 ──┘

4. Расширение запроса и вопросы с несколькими этапами обработки

На этапе расширения запроса необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения работы перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг, исходя из известной точки контроля, без необходимости угадывать скрытое состояние. Лучше использовать небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага причина должна быть связана с конкретной областью ответственности, а не с запутанной структурой обработки данных. Необходимо указывать конкретные фрагменты текста, на которых основан ответ. Без цитат операторы не смогут отличить галлюцинации от пробелов в индексации.

Что показала оценка на Kaggle

На этапе оценки в Kaggle необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг, используя известную точку контроля, без необходимости угадывания скрытого состояния. Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Укажите названия создаваемых файлов, определите критерии успеха и не допускайте молчаливого частичного выполнения задачи. Цитируйте те фрагменты, на которых действительно основан ответ. Без цитат операторы не смогут отличить галлюцинации от пробелов в индексации.

Расширение запроса без изменения его цели

При расширении запроса без использования этапов необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Записывайте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Отображение стоимости заранее помогает избежать неожиданных счетов при переходе с демо-среды в общедоступные среды. Указывайте конкретные фрагменты текста, на которых основан ответ. Без цитат операторы не могут отличить галлюцинации от пробелов в индексации. При расширении запроса без использования этапов необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Документируйте одновременно успешный сценарий работы и сценарий восстановления. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не последующими улучшениями.

Расширение запроса не является тем же, что и генерация подзапросов

При работе над этапом расширения запроса сначала запишите условия работы: необходимые входные данные, сигнал успешного выполнения и последствия частичной неудачи. Такой чек-лист поможет сохранять честность при последующих изменениях кода. Лучше использовать небольшие, тестируемые единицы кода вместо обширных скриптов. Если какой-то шаг не сработает, проблема должна быть связана с конкретной функцией, а не с запутанной цепочкой операций. Перед настройкой подсказок измерьте уровень воспроизводимости ответов на фиксированном наборе вопросов. Частая смена подсказок редко помогает улучшить качество поиска.

Результативная стратегия запросов

На этапе разработки стратегии запросов сначала запишите условия соглашения: необходимые входные данные, сигнал успешного выполнения и действия при частичной неудаче. Такой чек-лист поможет избежать недоразумений при последующих изменениях кода. Рассматривайте этот этап как соглашение между входными данными и проверенными выходными результатами. Дайте названия соответствующим элементам, определите критерии успеха и не допускайте молчаливого частичного выполнения задачи. Оцените уровень воспроизводимости на фиксированном наборе вопросов перед настройкой подсказок. Частая смена подсказок редко помогает улучшить качество поиска.

На этапе заключительных размышлений сначала запишите условия работы системы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Рядом с результатами работы запишите время выполнения и стоимость использования токенов или запросов. Отображение затрат с самого начала предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам. Перед настройкой инструкций для системы измерьте её способность к воспроизведению ответов на фиксированный набор вопросов. Частая смена инструкций редко помогает улучшить качество поиска. На этапе заключительных размышлений сначала запишите условия работы системы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Одновременно задокументируйте успешный сценарий работы и сценарий восстановления. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не элементами последующей доработки.

Чек-лист операционной работы

Этап проверки операционных процедур работает наилучшим образом, когда рассматривается как измеримая основа. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ.

Храните конфигурацию отдельно от кода приложения. Файлы среды, хранилища конфиденциальных данных и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код.

Разделяйте политику разбиения данных на части и политику их извлечения. Изменение одной из них не должно приводить к необходимости переписывания другой при изменении показателей качества.

При наличии бюджета добавляйте тесты на базовую работу, которые проверяют критически важные этапы в рамках CI с использованием фикстчеров, а не реальных платных API.

Документируйте как успешный, так и восстановительный пути работы одновременно. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не элементами последующей доработки.

Необходимо разделять политику сегментации данных и политику их извлечения. Изменение одной из них не должно принуждать к переписыванию другой при изменении показателей качества.

Перед внедрением новой системы следует заморозить существующие версии, сохранить эталонный вариант записи данных для критически важных этапов и уточнить шаги для возврата к предыдущему состоянию. В совместных средах необходимы ограничения на частоту запросов, проверки принадлежности пользователей и четко определенный ответственный за обновление секретов. Лучше выбирать надежность, чем креативные одноразовые демонстрации.

Примечание для версии 8a4b50ff4af2: не храните ключи поставщика в репозитории, установите лимит токенов на сессию и сохраняйте записи данных рядом с фиксами для оценки, чтобы последующие замены моделей оставались сопоставимыми.