Погружаемся в продвинутые методы: заставляем модель рассуждать пошагово, структурируем её ответы и отлавливаем галлюцинации. Учимся разбивать документы на смысловые чанки и запускаем LLM прямо у себя на ноутбуке — без облаков и API.
Что думает Anthropic о создании эффективных агентов
Контекст — это всё. Агент не «знает» ничего сам по себе. Он работает с тем, что вы ему подаёте: промпт, структура, история диалога.
Агент — это не один промпт, а последовательность шагов. Рекомендуется строить агентов как процессы, где LLM делает выводы, принимает решения, хранит промежуточные данные и передаёт их между этапами.
Состояние — важно. Агент, который делает запрос и передаёт результат в другой этап, должен понимать своё состояние. Без этого он становится болтуном с амнезией.
Используйте несколько промптов. Один — на анализ, другой — на выбор действия, третий — на генерацию, четвёртый — на проверку и улучшение. Это архитектура, а не просто одна длинная подсказка.
Вывод: LLM — это строительный блок. Настоящий агент — это архитектура + оркестрация. В этом помогает Directual.
Structured Output — чтобы не просто говорил, а работал
Когда вы хотите, чтобы ассистент возвращал не просто текст, а структурированные данные, нужно использовать Structured Output.
Это может быть JSON, XML, markdown, таблица и т.д.
Зачем это нужно:
Легко парсить и использовать в сценариях Directual
Проверка корректности ответа
Чёткий контроль формата
Как настроить Structured Output на Directual
Есть два подхода как настроить SO на платформе Directual
Response Format
Это вариант, когда мы добавляем в запрос "response_format": { "type": "json_object" }, а стурктуру ответа указываем прямо в системном промпте. Код запроса ниже:
{
"model": "gpt-3.5-turbo",
"response_format": { "type": "json_object" },
"messages": [
{
"role": "system",
"content": "Respond strictly with a JSON object containing the fields: title (string), summary (string), items (array of strings)." },
{
"role": "user",
"content": "Compose a summary: {{#escapeJson}}{{text}}{{/escapeJson}}" }
]
}
Function Calling
Этот вариант подразумевает использование tools. Формат ответа в этом случае гарантирован. Код запроса ниже:
Если нужен другой формат (например, XML) — указывается прямо в тексте промпта.
{
"model": "gpt-3.5-turbo",
"messages": [
{
"role": "system",
"content": "You are an assistant that always returns output in valid XML format. Wrap the entire response in a single <response> root tag. Do not include any explanation or commentary. Output only XML. Tags inside: title (string), summary (string), items (array of strings)." },
{
"role": "user",
"content": "Compose a summary: {{#escapeJson}}{{text}}{{/escapeJson}}" }
]
}
Chain of Thought — заставляем LLM думать вслух
Chain of Thought (CoT) — техника, где модель размышляет пошагово. Это:
повышает точность
позволяет отслеживать логику
помогает отлавливать ошибки
Комбо: CoT + Structured Output
Модель размышляет
Возвращает финальный JSON
Можно хранить рассуждения для логов, а пользователю показывать только результат.
На выходе мы получаем JSON вида, с которым уже можно работать далее в сценарии:
{
"steps": [
{
"explanation": "We start with the equation 8x + 7 = -23. Our goal is to solve for x.",
"output": "8x + 7 = -23" },
{
"explanation": "To isolate the term with x, we first need to get rid of the constant on the left side. We do this by subtracting 7 from both sides of the equation.",
"output": "8x = -23 - 7" },
{
"explanation": "Simplify the right side by performing the subtraction, which gives us -30.",
"output": "8x = -30" },
{
"explanation": "Now, we need to solve for x. Since 8 is multiplied by x, we divide both sides of the equation by 8 to isolate x.",
"output": "x = -30 / 8" },
{
"explanation": "Simplify the right side by performing the division, and reduce the fraction to its simplest form. -30 divided by 8 is -3.75, which can also be expressed as the fraction -15/4.",
"output": "x = -3.75 or x = -15/4" }
],
"final_answer": "x = -3.75 or x = -15/4"}
Возвращаемся к RAG — про чанкинг
Когда документов становится много и они длинные — нужно делить их на чанки.
Почему это важно:
У моделей есть лимит контекста
Слишком длинные тексты плохо векторизуются
Подходы к чанкингу
В Directual удобно сделать чанкинг в три шага:
Разбить текст на JSON-объект вида { "chunks": [ { "text" : "..." }, { "text": "..." },... ] }
Применить JSON-шаг для создания объектов в структуре Chunks
Отправлять массив объектов в шаг LINK scenario, и там делать эмбеддинг и прокидывать обратную ссылку на родительский документ.
Есть три метода разбиения текста на чанки:
1. По длине
Например, 100 слов, с overlap 10
Код для создания JSON ниже.Обратите внимание, что для использования стрелочных функций необходимо в шаге START => Advanced включить ECMAScript 2022 (ES13), по умолчанию работает ES6. Также при сохранении JS-объекта в поле типа json необходимо оборачивать выражение в JSON.stringify().
JSON.stringify({
"chunks": _.chain(`{{text}}`.split(/\s+/))
.thru(words => {
const chunkSize = 100;
const overlap = 10;
const chunks = [];
for (let i = 0; i < words.length; i += (chunkSize - overlap)) {
chunks.push({ text: words.slice(i, i + chunkSize).join(' ') });
}
return chunks;
})
.value()
})
Плохой чанкинг = однотипные ответы, обрывы логики, "ничего не найдено".
2. По структуре
Разделяем на абзацы. Если чанк менее 5 слов, склеиваем его со следующим, потому что, скорее всего, это заголовок.
Код для шага Edit object:
JSON.stringify({
"chunks": _.chain(`{{text}}`.split(/\n+/))
.map(_.trim)
.filter(p => p.length > 0)
.thru(paragraphs => {
const chunks = [];
let i = 0;
while (i < paragraphs.length) {
const current = paragraphs[i];
if (current.split(/\s+/).length < 5 && i + 1 < paragraphs.length) {
chunks.push({ text: current + ' ' + paragraphs[i + 1] });
i += 2;
} else {
chunks.push({ text: current });
i += 1;
}
}
return chunks;
})
.value()
})
3. По смыслу
Делаем запрос в ChatGPT:
{
"model": "gpt-4o",
"response_format": { "type": "json_object" },
"messages": [
{
"role": "system",
"content": "You are a helpful assistant that splits text into meaningful semantic chunks. Each chunk should represent a coherent idea, paragraph, or topic segment. Return your output strictly as a JSON object with the structure: { \"chunks\": [ {\"text\": \"...\"} ] }." },
{
"role": "user",
"content": "Split the following text into semantic chunks:{{#escapeJson}}{{text}}{{/escapeJson}}" }
]
}
Как понять, что чанкинг плохой?
Плохой чанкинг = однотипные ответы, обрывы логики, "ничего не найдено".
Как тестировать LLM на галлюцинации — logprobs
Logprobs = log-вероятность каждого токена.
Высокий logprob (ближе к 0) — уверенность
Низкий logprob — модель сомневается
Используем это для фильтрации ненадёжных ответов.
Что делать:
Не показывать сомнительные ответы
Перегенерировать
Показать вариант с предупреждением
В связке с Structured Output — можно проверять уверенность по конкретным полям.
На Directual делаем:
Шаг запроса с logprobs: true
Визуализация HTML (цвет по уровню уверенности)
Код для визуализации ответа модели с logprobs: true:
Присоединяйтесь к нашему уютному сообществу: получите помощь с проектами, найдите потенциальных сооснователей, пообщайтесь с разработчиками платформы и многое другое.