Документация
Документация GroUvi API: приватный режим и файлы
GroUvi API работает в формате OpenAI: любая библиотека, бот или приложение, которые умеют OpenAI, работают и здесь. Приватный режим прячет персональные данные до того, как они попадут в модель, и умеет работать с документами целиком.
Адреса и ключи
https://ai.grouvi.online/v1Прямо на наш сервер в Москве: TLS заканчивается там, до маскировки. Режим задаёт ключ: ключ группы «Приватная» скрывает персональные данные.Ключ передаётся в заголовке Authorization: Bearer sk-.... Ключи создаются в консоли, раздел «Ключи API»: для приватного режима выберите группу «Приватная — маскировка персональных данных».
Запросы к моделям
POST /v1/chat/completions, как в OpenAI, с потоковой выдачей и инструментами. В приватном режиме в тело можно добавить два поля: grouvi_mask.terms — свои слова, которые надо скрыть, и grouvi_mask.off — типы данных, которые остаются открытыми. Ответ приходит с настоящими данными на местах и полем grouvi_mask.masked: что скрыто, по типам.
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. Мы читаем его у себя, маскируем вместе с перепиской, и модель получает его текст. Картинки уходят распознанным текстом.
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, чтобы вернуть настоящие данные.
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 "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 секунд на страницу.