Главная / Статьи / Практические заметки: лучшие практики команды MiniMax Agent — искусственный интеллект-агент представляет собой цикл while.

Практические заметки: лучшие практики команды MiniMax Agent — искусственный интеллект-агент представляет собой цикл while.

Пошаговое руководство по использованию «Практических заметок: Лучшие практики команд MiniMax Agent — искусственный интеллект-агент как цикл While», включающее контракты, проверки и готовые блоки кода для команд, внедряющих эту схему.

2148 слов

Используйте это как переработанную версию идей из статьи «Лучшие практики команды MiniMax Agent: Искусственный интеллект-агент — это цикл while. Надежный агент — это машина состояний», ориентированную на операторов: четкие этапы, упорядоченные блоки кода и записи о восстановлении, сохраняющиеся при передаче задачи. Этап Обзора работает наилучшим образом, если рассматривать его как измеримую основу. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия создаваемым элементам, определите критерии успеха и не соглашайтесь на молчаливое частичное выполнение задачи.

# naive_loop.py -- a single-agent tool loop,
# Mini-Agent style: summarize if needed ->
# llm.generate(messages, tools) -> execute
# tool_calls -> append results -> repeat.
import json
import subprocess
from openai import OpenAI

client = OpenAI()
MODEL = "gpt-4o-mini"
MAX_HISTORY = 40  # crude context budget


def read_file(path: str) -> str:
    with open(path) as f:
        return f.read()[:4000]


def run_cmd(cmd: str) -> str:
    p = subprocess.run(
        cmd, shell=True, timeout=30,
        capture_output=True, text=True)
    out = p.stdout + p.stderr
    return f"exit={p.returncode}\n{out[-2000:]}"


TOOLS = {"read_file": read_file,
         "run_cmd": run_cmd}


def schema(name, desc, arg):
    return {
        "type": "function",
        "function": {
            "name": name,
            "description": desc,
            "parameters": {
                "type": "object",
                "properties": {
                    arg: {"type": "string"},
                },
                "required": [arg],
            },
        },
    }


SCHEMAS = [
    schema("read_file",
           "Read a local text file.", "path"),
    schema("run_cmd",
           "Run a shell command.", "cmd"),
]



def summarize(msgs):
    # Mini-Agent compresses old turns with an
    # LLM summary call when the context nears
    # its limit; hard truncation is the v0.
    if len(msgs) <= MAX_HISTORY:
        return msgs
    return [msgs[0]] + msgs[-MAX_HISTORY:]


def run(task: str, max_steps: int = 20):
    msgs = [{"role": "user", "content": task}]
    for _ in range(max_steps):
        msgs = summarize(msgs)
        r = client.chat.completions.create(
            model=MODEL,
            messages=msgs,
            tools=SCHEMAS,
        )
        msg = r.choices[0].message
        msgs.append(msg)
        if not msg.tool_calls:
            return msg.content  # model says done
        for call in msg.tool_calls:
            fn = TOOLS[call.function.name]
            args = json.loads(
                call.function.arguments)
            try:
                out = fn(**args)
            except Exception as e:
                out = f"tool error: {e}"
            msgs.append({
                "role": "tool",
                "tool_call_id": call.id,
                "content": out,
            })
    return "hit max_steps -- gave up"


if __name__ == "__main__":
    print(run("Count the .py files here, then "
              "summarize naive_loop.py."))
# team_engine.py -- the loop promoted to a
# state machine. One task lifecycle is one
# Session; deterministic code owns every
# transition: producing -> verifying -> done.
from dataclasses import dataclass, field

PRODUCING = "producing"
VERIFYING = "verifying"
DONE = "done"
FAILED = "failed"


@dataclass
class Session:
    goal: str
    state: str = PRODUCING
    attempts: int = 0
    artifact: str = ""
    reviews: list = field(default_factory=list)


def run_session(s, worker, verifier,
                max_retries: int = 3):
    while s.state not in (DONE, FAILED):
        if s.state == PRODUCING:
            s.attempts += 1
            s.artifact = worker(
                s.goal, s.reviews)
            s.state = VERIFYING
        elif s.state == VERIFYING:
            ok, report = verifier(
                s.goal, s.artifact)
            s.reviews.append(report)
            if ok:
                s.state = DONE
            elif s.attempts >= max_retries:
                s.state = FAILED
            else:
                # Reject: wake the worker with
                # the review log in context.
                s.state = PRODUCING
    return s


def run_team(goals, worker, verifier):
    # Leader's job: split the goal, run the
    # sessions (a thread pool in real use),
    # then merge N artifacts into 1 result.
    done, failed = [], []
    for g in goals:
        s = run_session(Session(g),
                        worker, verifier)
        if s.state == DONE:
            done.append(s.artifact)
        else:
            failed.append(s.goal)
    return done, failed


if __name__ == "__main__":
    # Stub roles so the engine runs anywhere;
    # swap in LLM calls for the real thing.
    def worker(goal, reviews):
        v = len(reviews) + 1
        return f"draft v{v}: {goal}"

    def verifier(goal, artifact):
        ok = "v2" in artifact
        return ok, f"review {artifact!r}: {ok}"

    done, failed = run_team(
        ["intro", "benchmarks", "faq"],
        worker, verifier)
    print("delivered:", done)
    print("failed:", failed)
# grounded_verifier.py -- evidence over vibes.
# The verdict comes from exit codes and logs,
# never from the model's self-assessment.
import subprocess
import sys

PY = sys.executable

# pytest exit codes: 0 = all passed,
# 1 = failures, 5 = no tests collected
# (acceptable for a docs-only change).
PYTEST_OK = (0, 5)

CHECKS = [
    ("diff", ["git", "diff", "--stat"], (0,)),
    ("build", [PY, "-m", "compileall",
               "-q", "."], (0,)),
    ("tests", [PY, "-m", "pytest", "-q",
               "--maxfail", "1"], PYTEST_OK),
]


def run_check(name, cmd, ok_codes, cwd):
    p = subprocess.run(
        cmd, cwd=cwd,
        capture_output=True, text=True)
    tail = (p.stdout + p.stderr)[-2000:]
    return {
        "check": name,
        "cmd": " ".join(cmd),
        "exit_code": p.returncode,
        "ok": p.returncode in ok_codes,
        "output_tail": tail,
    }


def verify(repo: str):
    evidence = []
    for name, cmd, ok_codes in CHECKS:
        e = run_check(name, cmd, ok_codes, repo)
        evidence.append(e)
        if not e["ok"]:
            # Reject with logs attached: the
            # worker retries against real
            # errors, not "please improve".
            return False, evidence
    return True, evidence



if __name__ == "__main__":
    ok, ev = verify(".")
    for e in ev:
        print(f"{e['check']:>6} exit "
              f"{e['exit_code']} ok={e['ok']}")
    print("verdict:", "pass" if ok else "fail")

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

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

Лучше использовать небольшие, тестируемые единицы вместо обширных скриптов. Когда какой-то шаг терпит неудачу, причина должна быть связана с конкретной функцией, а не с запутанной цепочкой операций.

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

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

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

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

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

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

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

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

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

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

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

Подробности усиления безопасности 2/726: измеряйте время выполнения, класс ошибки и расход токенов для этой записи, затем принимайте решение о сохранении изменений на основе фиксированного набора вопросов, а не на основе устных описаний.

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

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

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

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

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

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

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

Подробности усиления безопасности 6/726: измеряйте время выполнения, класс ошибок и затраты на токены для данной стадии, а затем принимайте решение о сохранении изменений на основе фиксированного набора критериев, а не на основе устных оценок.

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

Деталь укрепления безопасности 7/726: измерьте время выполнения, класс ошибки и расход токенов для данной записки, затем решите, следует ли сохранять изменение, опираясь на заранее определенный набор критериев, а не на устные оценки.

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

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

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

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

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

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