awesome-everything EN
↑ Обратно к восхождению

AI / LLM

Сборка LLM-приложений: чтение кода и трейсов

Суть Читай реальные сниппеты композиции — раскладку кэша, state machine стрим/тулзы, agent loop с бюджет-гейтом и RAG retrieve+inject — и выбирай фикс с наибольшим рычагом.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 14 min

Швы видны в коде, не на слайдах. Читай каждый сниппет так, как читал бы PR для production LLM-фичи: найди границу, где один слой тихо нарушает допущение следующего, и выбери фикс, который senior-инженер делает первым.

Цель

Отработай цикл, который гоняешь при сборке слоёв: прочитай раскладку запроса или цикл, найди границу, ломающуюся под реальным трафиком, и тянись к структурному фиксу — а не к ручке тюнинга.

Сниппет 1 — раскладка кэша

system = [
    {"type": "text", "text": SYSTEM_RULES},          # статика
    {"type": "text", "text": tool_schemas_json},      # статика
    {"type": "text", "text": "Relevant docs:\n" + retrieved_chunks,
     "cache_control": {"type": "ephemeral"}},          # попроцессный RAG, затем брейкпойнт
]
resp = client.messages.create(model=MODEL, system=system,
                              messages=[{"role": "user", "content": query}])
Викторина

Брейкпойнт стоит после полученных чанков. Что эта раскладка реально кэширует и как это починить?

Сниппет 2 — state machine стрима / тулзы

async for event in stream:
    if event.type == "content_block_delta":
        ui.append(event.delta.text)
    elif event.type == "message_stop":
        ui.done()                       # спиннер гаснет здесь
# (других веток нет)
Викторина

Ход с тулзой стримит текст, затем заканчивается с stop_reason: tool_use. Протрассируй поведение этого цикла и выбери фикс.

Сниппет 3 — agent loop

def run_agent(task):
    msgs = [task]
    while True:
        resp = client.messages.create(model=MODEL, messages=msgs, tools=TOOLS)
        if resp.stop_reason != "tool_use":
            return resp
        for call in tool_uses(resp):
            msgs.append(tool_result(call, execute(call)))   # транскрипт растёт каждый цикл
Викторина

Malformed-результат тулзы заставляет модель переформулировать и вечно повторять тот же вызов. Сколько это стоит и какой минимальный фикс?

Сниппет 4 — RAG retrieve + расчёт стоимости

hits = vectordb.query(embed(user_q), top_k=20)        # без rerank, без порога
context = "\n".join(h.text for h in hits)             # ~20 чанков × ~800 ток ≈ 16k ток
# input ≈ 16k контекст + 2k промпт = 18k ток; цена $3 / 1M input ток
cost_per_call = 18_000 / 1_000_000 * 3                # ≈ $0.054, на каждый запрос, без кэша
Викторина

Этот retrieve-and-inject путь корректен в изоляции, но дорог в собранном приложении. Прочитай числа и выбери изменение с наибольшим рычагом.

Итог

Баги композиции видны в коде: брейкпойнт кэша, поставленный после попроцессных RAG-чанков, не кэширует ничего переиспользуемого; стрим-цикл без ветки tool_use гасит UI, пока модель ждёт tool_result; agent loop без гейта step/budget вечно пересылает растущий транскрипт; а неранжированный top-20 retrieval впрыскивает ~16k некэшируемых токенов по ~$0.054 за вызов. Фикс в каждом случае структурный — перенести динамику, ветвиться по stop_reason, загейтить цикл, переранжировать контекст — а не ручка тюнинга.

Продолжить восхождение ↑Капстоун: выкати собранную LLM-фичу, держащую на швах
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.