Настройка и первый вызов
Это независимый OpenAI-совместимый сервис, а не собственный API Codex от OpenAI. Его единственная модель — open-weight, только текст, и она достаточно хорошо справляется с задачами генерации, объяснения и рефакторинга кода, которые всё равно стоит проверять. Если вам сначала нужна предыстория, страница об API Codex от OpenAI объясняет, как они связаны.
Установите SDK командой pip install openai, создайте ключ на странице API-ключ и запустите:
# pip install openai
from openai import OpenAI
client = OpenAI(base_url="https://api.getcodexapi.com/v1", api_key="YOUR_KEY")
resp = client.chat.completions.create(
model="uncensored",
messages=[
{"role": "system", "content": "You are a senior Python developer. Reply with code only, no commentary."},
{"role": "user", "content": "Write a function that parses an ISO 8601 date string and returns a datetime."},
],
temperature=0.2,
)
print(resp.choices[0].message.content)Пробный баланс новых пользователей в размере $0,50 покрывает тысячи небольших вызовов, подобных этому. Температура равна 0,2, так как код выигрывает от меньшей случайности. Если вы видите разметку в виде блока кода вокруг ответа, удалите её в коде или запросите в системном сообщении чистый текст. На странице базового URL Codex API base URL указан точный адрес снова.
Промптинг для кода, который работает
Несколько привычек улучшают результат больше, чем любые параметры.
- Укажите язык и версию. "Python 3.11, только стандартная библиотека" устраняет множество догадок.
- Дайте сигнатуру. Вставьте заголовок функции и docstring и попросите модель заполнить тело.
- Покажите один пример ввода и вывода. Это лучше, чем текст, фиксирует граничные случаи.
- Просите одно. Сгенерируйте функцию, а затем запросите тесты отдельным вызовом.
- Запросите diff для правок. Переписывание всего файла сжигает токены вывода, которые стоят дороже ввода.
Контекстное окно составляет 100 000 токенов, а max_tokens необязателен. Для задачи по коду вы можете вставить несколько модулей и всё равно иметь место для ответа. Установка max_tokens полезна только как страховка от неконтролируемого вывода.
JSON-режим для структурированных результатов
Когда код потребляет ответ, используйте JSON-режим. Он делает вывод валидным JSON; он не навязывает вашу схему, поэтому укажите имена ключей в промпте и проверьте их.
import json
from openai import OpenAI
client = OpenAI(base_url="https://api.getcodexapi.com/v1", api_key="YOUR_KEY")
resp = client.chat.completions.create(
model="uncensored",
response_format={"type": "json_object"},
messages=[
{"role": "system", "content": "Return JSON with keys: name, args (list of strings), returns."},
{"role": "user", "content": "Describe the signature of: def clamp(x, lo, hi)."},
],
temperature=0,
)
data = json.loads(resp.choices[0].message.content)
print(data["name"], data["args"])Сочетайте это с блоком try/except вокруг json.loads и одной повторной попыткой, отправляющей ошибку парсинга обратно. На практике это обрабатывает редкие некорректные ответы. Используйте температуру 0, чтобы повторяющиеся запуски совпадали.
Вызов функций
С помощью инструментов вы описываете функции, а модель решает, когда их вызывать. Вы запускаете функцию, затем отправляете результат обратно с ролью tool. Это основа любого кодового агента.
import json
from openai import OpenAI
client = OpenAI(base_url="https://api.getcodexapi.com/v1", api_key="YOUR_KEY")
tools = [{
"type": "function",
"function": {
"name": "run_tests",
"description": "Run the project's test suite and return the output.",
"parameters": {
"type": "object",
"properties": {"path": {"type": "string"}},
"required": ["path"],
},
},
}]
messages = [{"role": "user", "content": "Run the tests in tests/unit and tell me what failed."}]
first = client.chat.completions.create(model="uncensored", messages=messages, tools=tools, tool_choice="auto")
msg = first.choices[0].message
if msg.tool_calls:
call = msg.tool_calls[0]
args = json.loads(call.function.arguments)
output = "2 passed, 1 failed: test_parse_empty" # replace with a real runner
messages.append(msg)
messages.append({"role": "tool", "tool_call_id": call.id, "content": output})
final = client.chat.completions.create(model="uncensored", messages=messages, tools=tools)
print(final.choices[0].message.content)Тестируйте сгенерированный код так же, как и любой другой: запускайте его, проверяйте линтером и сохраняйте небольшой набор промптов с заведомо правильными результатами, чтобы замечать, когда изменение промпта ухудшает результаты. Закрепите seed и температуру при сравнении версий.
Примечания: держите описания инструментов короткими и дословными, проверяйте аргументы перед запуском и никогда не передавайте вывод модели напрямую в оболочку. Для цикла повторяйте вызов, пока присутствует tool_calls, и останавливайтесь после максимального числа шагов. Каждый шаг повторно отправляет историю, поэтому запуск на десять шагов стоит примерно в десять раз больше.
Потоковая передача и повторная попытка при 429
Для интерактивных инструментов передавайте токены потоком по мере их поступления. Данные об использовании поступают в конце потока, что упрощает логирование стоимости.
import time
from openai import OpenAI, RateLimitError
client = OpenAI(base_url="https://api.getcodexapi.com/v1", api_key="YOUR_KEY", max_retries=0)
def ask(prompt, tries=4):
for attempt in range(tries):
try:
stream = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": prompt}],
stream=True,
stream_options={"include_usage": True},
)
text = []
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
piece = chunk.choices[0].delta.content
text.append(piece)
print(piece, end="", flush=True)
if chunk.usage:
print("\ntokens:", chunk.usage.prompt_tokens, chunk.usage.completion_tokens)
return "".join(text)
except RateLimitError:
time.sleep(5 * (attempt + 1))
raise RuntimeError("still rate limited")
ask("Explain Python generators in four sentences.")Лимиты за этим циклом повторных попыток: полный ключ позволяет 8 параллельных запросов и 300 в минуту, а пробный ключ — 2 и 60. При превышении лимита вы получаете HTTP 429 с кодом rate_limited или concurrency. Временная перегрузка также даёт 429 с заголовком Retry-After: 5. В примере на клиенте установлено max_retries=0, чтобы ваш собственный цикл контролировал паузы. Потоковый запрос удерживает слот параллельности до завершения потока, поэтому всегда потребляйте или закрывайте поток.
Выполнение множества запросов одновременно
Пакетные задания, такие как генерация тестов для ста функций, требуют ограничения параллелизма. Используйте пул потоков с максимум 8 рабочими для полного ключа.
Простой шаблон — ThreadPoolExecutor(max_workers=6) вокруг функции, вызывающей ask, оставляя два слота свободными для другой работы. Для пробного ключа используйте 2 рабочих. Если вы передадите большее число, API ответит на дополнительные запросы ошибками concurrency, и ваш цикл повторных попыток потратит время на ожидание, а не на работу. Для асинхронного кода используйте AsyncOpenAI с asyncio.Semaphore(6) вокруг каждого вызова; это даёт то же ограничение без потоков. Заголовки ответа X-RateLimit-Limit-Requests и X-RateLimit-Limit-Concurrency показывают лимиты для вашего ключа.
Стоимость задач по коду
Цена составляет $0,15 за 1 млн входных токенов и $0,50 за 1 млн выходных токенов. Предположим, вы генерируете модульные тесты для 200 функций. Каждый вызов отправляет 1 500 входных токенов и возвращает 700 токенов. Ввод: 200 x 1 500 = 300 000 токенов или $0,045. Вывод: 200 x 700 = 140 000 токенов или $0,07. Итого: $0,115.
Рефакторинг большого файла отправляет 30 000 токенов и получает 8 000: $0,0045 + $0,004 = $0,0085 за запуск. Неудачные или отклонённые запросы не оплачиваются, а кредит никогда не сгорает. Пополнения начинаются от $20 и могут быть оплачены картой или криптовалютой, с бонусом 5% от $50, 10% от $100 и 15% от $200. См. цены и прочтите документацию для полного списка параметров.

