КурсХакатон Apache DorisЗадания в своём темпе · начните в любое время · без регистрации

Трек A · Задание A4

Обозреватель трассировок агентов

ИИ-агенты выдают JSON, структура которого меняется с каждым релизом. Храните его в VARIANT и запрашивайте как обычные столбцы.

  • 60–120 мин
  • Средний уровень
  • Любой язык · CLI, блокнот или веб
  • ИИ-инструменты приветствуются

Нужна помощь? Спросите в #dev в Slack Apache Doris. Разработчики и другие участники помогут вам.

1

Подготовка

Что вы создаёте, почему Doris упрощает задачу и как запустить кластер.

Что вы создадите

JSON агента разнороден. Всё равно запрашивайте его.

Вызовы LLM, вызовы инструментов, ошибки, итоговые ответы: у каждого свои поля, а каждый релиз добавляет новые. Doris VARIANT автоматически преобразует JSON в типизированные столбцы, позволяя фильтровать, искать и агрегировать обычным SQL. Без миграций схемы.

Обозреватель трассировок для 1,000 сессий ИИ-агента (около 20,000 событий):

  • одним списком сессий с числом событий, ошибками, токенами и задержкой,
  • одним хронологией сессии: нажмите сессию, чтобы пошагово воспроизвести действия агента,
  • статистикой инструментов и моделей: задержка p95, доля ошибок, расход токенов,
  • поиском внутри JSON: найдите все ошибки инструментов с упоминанием «timeout».

Затем ответьте: Стало лучше или хуже после выпуска v2 агента, развёрнутого в 13:00?

ЭскизЧто вы создадите · схема интерфейса, не снимок экрана

Эскиз находится в верхней части панели кода

Почему это интересно на Doris

  • Схема при записи без задания схемы. VARIANT определяет тип каждого пути JSON и сохраняет частые пути как настоящие колоночные подстолбцы, поэтому payload['latency_ms'] читает один столбец, а не разбирает каждый документ.

  • Новые поля появляются автоматически. Когда события v2 добавляют cost_usd, новый путь появляется как подстолбец при следующей загрузке, без ALTER TABLE.

  • Поиск внутри JSON. Инвертированный индекс на VARIANT позволяет искать по любому текстовому пути с помощью MATCH_*.

Панель: строки индексов в определении таблицы

Перед началом

  • docker pull apache/doris:all-in-one-4.1.3
  • docker run -d --name doris -p 9030:9030 -p 8030:8030 -p 8040:8040 apache/doris:all-in-one-4.1.3
  • docker exec -it doris mysql -uroot -h127.0.0.1 -P9030
  • curl -LO https://github.com/morningman/demo-env/releases/download/for-hackathon/doris-hackathon-glasgow-2026.zip && unzip doris-hackathon-glasgow-2026.zip && cd doris-hackathon-glasgow-2026
Хост
127.0.0.1
Порт
9030
Пользователь
rootбез пароля
База данных
hackathon

Данные

hackathon.agent_events : по строке на событие агента, содержимое события в столбце VARIANT:

Таблицаhackathon.agent_events · sql
CREATE TABLE agent_events (  session_id  VARCHAR(40)  NOT NULL,  ts          DATETIME(3)  NOT NULL,  event_id    BIGINT       NOT NULL,  event_type  VARCHAR(32)  NOT NULL,   -- user_message / llm_call / tool_call / error / final_answer  payload     VARIANT      NOT NULL,  INDEX idx_payload (payload) USING INVERTED PROPERTIES ("parser" = "english"))DUPLICATE KEY(session_id, ts)DISTRIBUTED BY HASH(session_id) BUCKETS 1PROPERTIES ("replication_num" = "1", "storage_format" = "V3");

Примеры данных: обратите внимание на различия структуры:

Примеры данныхjson
{"text": "Why did checkout fail at 11:40?", "lang": "en", "agent_version": "v1"}{"model": "model-large", "usage": {"input_tokens": 812, "output_tokens": 96}, "latency_ms": 1430, "agent_version": "v1"}{"tool": "sql_query", "args": {"sql": "SELECT ..."}, "latency_ms": 37, "status": "ok", "agent_version": "v1"}{"tool": "http_get", "args": {"url": "..."}, "latency_ms": 3012, "status": "error", "agent_version": "v1", "error": {"type": "Timeout", "message": "read timeout after 3000 ms calling https://api.internal/orders"}}

Сессии, начавшиеся в 13:00 или позже, работают на агенте v2: в данных указано "agent_version": "v2", а вызовы LLM в v2 добавляют флаг cache_hit . На этапе 5 вы загрузите события с полями, которых таблица ещё не видела.

Панель → Таблица: полное определение таблицы

Разработка с ИИ

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

  1. Вставьте контекстный промпт ниже в своего агента.

  2. Укажите ему справочные страницы из этого задания и AGENTS.md из стартового набора. Многие агенты читают этот файл самостоятельно.

  3. Перед встраиванием в код пусть агент выполнит каждый SQL-запрос на вашем работающем кластере.

  4. Ещё лучше подключите Doris MCP Server (см. задание A2), чтобы агент сам изучал схему и тестировал запросы.

Контекстный промптвставьте в своего агента
I'm building an agent trace explorer on Apache Doris 4.1 for a hackathon.Connection: MySQL protocol, 127.0.0.1:9030, user root, empty password, database `hackathon`.Use a plain MySQL driver and raw SQL.Table `agent_events`: session_id, ts DATETIME(3), event_id, event_type(user_message / llm_call / tool_call / error / final_answer), payload VARIANT(inverted index, english parser). Payload shapes differ by event_type. Every payload hasagent_version: "v1" before 13:00, "v2" from 13:00; v2 llm_calls add cache_hit.Doris SQL rules:1. Read JSON paths as payload['a']['b']. CAST to a concrete type before comparing,   sorting or aggregating: CAST(payload['latency_ms'] AS DOUBLE).2. VARIANT cannot be a key, a sort key or a join key.3. Text search inside JSON: payload['error']['message'] MATCH_ANY 'timeout'. Never LIKE.4. Percentiles: percentile_approx(expr, 0.95).5. `SET describe_extend_variant_column = true; DESC agent_events;` lists inferred subcolumns.6. To insert JSON yourself, CAST the text: CAST('{"a": 1}' AS JSON).Build: sessions list, session timeline, tool/model stats, and JSON search.Run every SQL statement against the live cluster first.

Типичные ловушки Doris для ИИ-агента

TrapWhat to do instead
Сравнение путей VARIANT без приведения типаCAST(payload['latency_ms'] AS INT); VARIANT нельзя использовать как ключ или столбец соединения
Ожидание, что DESC покажет пути JSONВыполните SET describe_extend_variant_column = true; сначала; затем DESC покажет все определённые подстолбцы и их типы
Использование LIKE '%term%' для текстового поискаcol MATCH_ANY 'a b' (OR), MATCH_ALL (AND), MATCH_PHRASE 'a b' . Они используют инвертированный индекс
Использование ORMПредпочтительны обычный драйвер MySQL и SQL напрямую: ORM могут генерировать неподдерживаемые Doris операторы
2

Реализуйте

6 этапов, M0 → M5. Панель следует за текущим шагом.

  1. Этап 010 мин

    Загрузите и изучите

    Из папки стартового набора:

    M0 · Загрузкаbash
    docker exec -i doris mysql -uroot -h127.0.0.1 -P9030 < seed/a4_agent_events.sql

    Затем в оболочке SQL:

    M0 · Изучениеsql
    USE hackathon;SET describe_extend_variant_column = true;DESC agent_events;     -- see the subcolumns Doris inferred: payload.tool, payload.usage.input_tokens, ...
    Проверка

    Загрузка сообщает: 1,000 сессий и 20,401 событие; DESC показывает около 20 payload.* путей, каждый с определённым типом.

  2. Этап 115 мин

    Запрашивайте пути JSON

    M1 · Запросы по путям JSONsql
    SELECT CAST(payload['tool'] AS STRING) AS tool, COUNT(*) AS callsFROM agent_eventsWHERE event_type = 'tool_call'GROUP BY toolORDER BY calls DESC;
    Проверка

    Пять инструментов; sql_query вызывается чаще всего (3,506 раз).

  3. Этап 215 мин

    Агрегируйте определённые подстолбцы

    M2 · Агрегация определённых подстолбцовsql
    SELECT CAST(payload['tool'] AS STRING) AS tool,       COUNT(*) AS calls,       percentile_approx(CAST(payload['latency_ms'] AS DOUBLE), 0.95) AS p95_ms,       SUM(CASE WHEN CAST(payload['status'] AS STRING) = 'error' THEN 1 ELSE 0 END) AS errorsFROM agent_eventsWHERE event_type = 'tool_call'GROUP BY toolORDER BY p95_ms DESC;
    Проверка

    python_exec имеет худший p95 (около 2.1 с); http_get чаще всего завершается ошибкой (425 ошибок).

  4. Этап 310 мин

    Поиск внутри JSON

    M3 · Поиск внутри JSONsql
    SELECT session_id, ts, CAST(payload['error']['message'] AS STRING) AS error_messageFROM agent_eventsWHERE payload['error']['message'] MATCH_ANY 'timeout'ORDER BY tsLIMIT 20;
    Проверка

    Всего 398 событий упоминают timeout. Подсчитайте их по часам: это первая подсказка о v2.

  5. Этап 420 мин

    Хронология сессии

    M4 · Хронология сессииsql
    SELECT ts, event_type,       CAST(payload['tool'] AS STRING)      AS tool,       CAST(payload['status'] AS STRING)    AS status,       CAST(payload['latency_ms'] AS INT)   AS latency_ms,       CAST(payload['text'] AS STRING)      AS textFROM agent_eventsWHERE session_id = 's-0042'ORDER BY ts;

    Постройте интерфейс вокруг этих запросов: список сессий → хронология → статистика.

    Проверка

    Сессия s-0042 содержит 25 событий: вопрос, вызовы LLM и инструментов (один неудачный sql_query, затем повторная попытка) и итоговый ответ.

  6. Этап 510 мин

    Наблюдайте эволюцию схемы

    M5 · Загрузка пакета с изменённой схемойbash
    docker exec -i doris mysql -uroot -h127.0.0.1 -P9030 < a4/drift_batch.sql   # events with new fields
    M5 · Запросы по новым полямsql
    SELECT CAST(payload['agent_version'] AS STRING) AS version,       COUNT(*) AS llm_calls,       ROUND(SUM(CAST(payload['cost_usd'] AS DOUBLE)), 2) AS cost_usdFROM agent_eventsWHERE event_type = 'llm_call'GROUP BY versionORDER BY version;

    Выполните DESC agent_events снова: новые пути уже есть. Никакого ALTER TABLE не было.

    Проверка

    Появляется третья версия, v2.1: только её вызовы LLM содержат cost_usd, а DESC теперь показывает payload.cost_usd и payload.retries.

3

Завершите работу

Пройдите проверку, покажите результат и получите значок.

Критерии готовности

Ваш контрольный список

Отправьте работу и получите значок

Участвуйте → отправьте работу → получите значок.

  1. Поместите свою работу в папку с именем вашего GitHub ID: код и README с описанием, инструкцией запуска, одним снимком экрана или GIF и перечнем использованных функций Doris.

  2. Откройте pull request и добавьте её в morningman/demo-env как doris-hackathon-glasgow-2026/<your-github-id>/. Сделайте fork и push или используйте в GitHub Add file → Upload files. Больше ничего заполнять не нужно.

  3. Поделитесь результатом в #dev в Slack Apache Doris: ссылкой на pull request или репозиторий и снимком экрана либо коротким демо. Вопросы, отправка работ и выдача значков происходят там.

Каждый участник задания получает значок участника Apache Doris: принятый pull request в Doris не требуется. Срока нет, работайте столько, сколько нужно. Можно участвовать командой, но это не обязательно. Укажите GitHub ID каждого участника в README.

Дополнительные цели

  • Используйте собственные трассировки. Экспортируйте локальные журналы сессий своего ИИ-агента (JSONL) и загрузите по одному CAST('…' AS JSON) на строку. Данные сохраняются в вашем локальном Doris.

  • Schema Template. Закрепите часто используемые пути через VARIANT<'latency_ms': INT, 'tool': STRING> в копии таблицы и сравните вывод DESC и поведение запросов. Заполните через INSERT … SELECT …, CAST(payload AS JSON): VARIANT нельзя напрямую привести к VARIANT с шаблоном.

  • Предложите помощнику изучить данные. Подключите Doris MCP Server (задание A2) и попросите помощника найти худшую сессию.

  • Классифицируйте ошибки через SQL (с вашим API-ключом): AI_CLASSIFY(CAST(payload['error']['message'] AS STRING), ['timeout', 'auth', 'bad input', 'other']). См. SQL-функции LLM.

Устранение неполадок и справочные материалы

SymptomFix
docker: command not found в macOSЗапустите Docker Desktop. Если он уже работает, создайте ссылку на CLI: sudo ln -s /Applications/Docker.app/Contents/Resources/bin/docker /usr/local/bin/docker
error getting credentials при загрузке образовУдалите поле credsStore из ~/.docker/config.json (только для локальной разработки)
port is already allocatedПорты 9030, 8030 или 8040 заняты, часто другим Doris. Проверьте работающие контейнеры (docker ps), либо опубликуйте другие порты хоста, например -p 19030:9030, и подключайтесь к 19030
The container name "/doris" is already in useВы уже запускали его раньше: docker start doris. Чтобы начать заново, docker rm -f doris (данные будут удалены)
Контейнер завершается или не переходит в состояние (healthy)Прочитайте docker logs doris. Обычно причина в памяти: выделите Docker Desktop не менее 6 GB (Settings → Resources). На Apple Silicon не добавляйте --platform linux/amd64
permission denied: ./doris.shПри распаковке потерялось право на выполнение: chmod +x doris.sh, либо выполните bash doris.sh start
Current database is not setВыполните USE hackathon; сначала или подключитесь с помощью -Dhackathon
score() function requires WHERE clause with MATCH function, ORDER BY and LIMITДобавьте MATCH_* предикат, ORDER BY score() DESC и LIMIT, и оставьте score() без обёртки (см. ловушки выше)
Если не получается больше 10 минутНапишите в #dev в Slack Apache Doris

Справочные материалы

Тип данных VARIANTСправочник SQL по VARIANTПолнотекстовый поискSQL-функции LLM

Хакатон Apache Doris

Все задания

Вернуться к курсу
  1. A160–120 минПриложение гибридного поискаОткрыть описание задания
  2. A245–90 минЗадавайте вопросы Doris через MCPОткрыть описание задания
  3. A360–120 минОбозреватель поиска по логамОткрыть описание задания
  4. A460–120 минОбозреватель трассировок агентовВы здесь
  5. B30–60 минТрек B · От документации к демоОткрыть описание задания