Документация

Документация GroUvi API: приватный режим и файлы

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

Адреса и ключи

Адрес API
https://ai.grouvi.online/v1Прямо на наш сервер в Москве: TLS заканчивается там, до маскировки. Режим задаёт ключ: ключ группы «Приватная» скрывает персональные данные.

Ключ передаётся в заголовке Authorization: Bearer sk-.... Ключи создаются в консоли, раздел «Ключи API»: для приватного режима выберите группу «Приватная — маскировка персональных данных».

Запросы к моделям

POST /v1/chat/completions, как в OpenAI, с потоковой выдачей и инструментами. В приватном режиме в тело можно добавить два поля: grouvi_mask.terms — свои слова, которые надо скрыть, и grouvi_mask.off — типы данных, которые остаются открытыми. Ответ приходит с настоящими данными на местах и полем grouvi_mask.masked: что скрыто, по типам.

Python
from openai import OpenAI

client = OpenAI(base_url="https://ai.grouvi.online/v1", api_key="sk-...")
reply = client.chat.completions.create(
    model="minimax-m3",
    messages=[{"role": "user", "content": "Напиши письмо Кузнецову Дмитрию, паспорт 4515 236781"}],
    extra_body={"grouvi_mask": {"terms": ["Орион"], "off": ["DATE"]}},
)
print(reply.choices[0].message.content)   # настоящие данные уже на месте

Файлы в запросе к модели

В приватном режиме документ можно положить прямо в сообщение — частью file с file_data, как в OpenAI. Мы читаем его у себя, маскируем вместе с перепиской, и модель получает его текст. Картинки уходят распознанным текстом.

Python
import base64

data = base64.b64encode(open("договор.pdf", "rb").read()).decode()
reply = client.chat.completions.create(
    model="minimax-m3",
    messages=[{"role": "user", "content": [
        {"type": "text", "text": "Кто заказчик и какой у него ИНН?"},
        {"type": "file", "file": {"filename": "договор.pdf",
                                  "file_data": f"data:application/pdf;base64,{data}"}},
    ]}],
)

Файловый API

POST /v1/files/mask принимает документ и возвращает тот же документ с заменёнными данными, его текст для модели и vault — зашифрованную таблицу замен. POST /v1/files/restore возвращает настоящие данные: в файл, который поправила модель (multipart: file и vault), или в текст (JSON: text и vault). Мы ничего не храним: vault лежит у вас и открывается только тем ключом, которым создан.

POST /v1/files/mask — поля формы (multipart/form-data)

filefile
Документ: docx, xlsx, pptx, pdf, csv, json, txt, png, jpeg, tiff, bmp, webp. До 25 МБ.
termsstring
Свои слова, которые надо скрыть: названия клиентов, проектов, внутренние коды. Через запятую или JSON-списком, до 200.
offstring
Типы, которые остаются открытыми, через запятую: например DATE,ADDRESS.

Ответ (JSON)

filenamestring
Имя файла — имена в нём тоже заменены.
formatstring
docx, xlsx, pptx, pdf, csv, json, text, png или jpeg.
mimestring
Тип содержимого возвращённого файла.
filebase64
Тот же документ с заменёнными данными. С ?download=1 ответом приходит сам файл.
textstring
Текст замаскированного документа для модели: таблицы строками, страницы PDF и слайды подписаны.
reportobject
Что скрыто, по типам (counts, total), сколько авторов убрано из файла, предупреждения.
entitiesarray
Каждое найденное значение с типом и заменой. Здесь ваши данные — храните у себя.
vaultstring
Таблица замен, зашифрованная на нашем сервере и привязанная к вашему ключу. Отправьте её в /files/restore, чтобы вернуть настоящие данные.
Python
import base64, requests

API = "https://ai.grouvi.online/v1"
KEY = {"Authorization": "Bearer sk-..."}

# 1. договор целиком: тот же .docx назад и текст для модели
r = requests.post(f"{API}/files/mask", headers=KEY,
                  files={"file": open("договор.docx", "rb")},
                  data={"terms": "Орион, Альфа-Строй"}).json()
open("договор-маска.docx", "wb").write(base64.b64decode(r["file"]))
print(r["report"])          # что скрыто, по типам
vault = r["vault"]          # сохраните: без него данные не вернуть

# 2. модель поправила договор: настоящие имена и реквизиты обратно в файл
back = requests.post(f"{API}/files/restore", headers=KEY,
                     files={"file": open("договор-правки.docx", "rb")},
                     data={"vault": vault}).json()
open("договор-итог.docx", "wb").write(base64.b64decode(back["file"]))

# 3. или вернуть данные в ответ модели
text = requests.post(f"{API}/files/restore", headers=KEY,
                     json={"vault": vault, "text": "Ответ модели..."}).json()["text"]
curl
curl "https://ai.grouvi.online/v1/files/mask?download=1" \
  -H "Authorization: Bearer sk-..." \
  -F file=@скан.pdf -D headers.txt -o скан-маска.pdf
# в headers.txt: X-Grouvi-Vault (ключ возврата) и X-Grouvi-Report (что скрыто)

Форматы

  • Word .docxТекст, таблицы, колонтитулы, сноски, примечания вместе с авторами, исправления, надписи, ссылки, свойства документа. Оформление сохраняется.
  • Excel .xlsxЯчейки, строковые результаты формул и строки внутри них, комментарии, кэши сводных таблиц, колонтитулы. Числа и формулы не трогаем.
  • PowerPoint .pptxСлайды, заметки, комментарии и диаграммы.
  • PDFТекст вырезается из файла, а подмена ставится на то же место. Поля форм, аннотации, ссылки, закладки и метаданные тоже очищаются.
  • Сканы и фотоТекст распознаётся на нашем сервере в Москве, данные закрашиваются на картинке; у скана в PDF появляется текстовый слой для поиска.
  • CSV, JSON, TXTCSV сохраняет разделитель и кавычки; в JSON маскируются только строковые значения.

Старые .doc, .xls и .ppt не принимаются — с подсказкой сохранить их в новом формате. Файл, текст которого не удалось проверить полностью, отклоняется, а не возвращается наполовину замаскированным.

Ошибки

no_key401
В заголовке Authorization нет ключа.
not_private_key403
Ключ не из приватной группы. Создайте его в разделе «Ключи API».
slow_down429
Больше 30 файлов в минуту на один ключ.
too_large413
Файл больше 25 МБ.
file_not_masked422
Формат не поддерживается, файл повреждён или защищён паролем, либо скан не удалось прочитать. В сообщении сказано, что именно.
masking_failed500
Маскировка не завершилась. Ничего не возвращено и никуда не отправлено.
bad_vault400
vault повреждён или выдан для другого ключа.
image_not_allowed400
В запросах к модели картинка уходит только распознанным текстом, а распознавание сейчас недоступно.

Ошибка приходит в виде {"error": {"code": "...", "message": "..."}}; message написан для людей.

Лимиты

  • Файлы: до 25 МБ, до 30 файлов в минуту на ключ, PDF до 300 страниц.
  • Запросы к моделям: лимит аккаунта в минуту указан в консоли.
  • Сканы: около 5–10 секунд на страницу.