support-bot-saas/docs/API.md
ed0ss c0527c9bf6
Some checks failed
CI / lint-backend (push) Has been cancelled
CI / lint-frontend (push) Has been cancelled
CI / build-backend (push) Has been cancelled
CI / build-frontend (push) Has been cancelled
fix: включить прокси для embedding-клиента, исправить ошибку 500 на /api/search
2026-07-13 18:02:00 +03:00

303 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# API
Базовый URL: `http://sovet.itoservice.ru/api/v1`
Авторизация: `Authorization: Bearer <api_key>`
> Получить API-ключ можно при регистрации через UI (отображается в настройках профиля).
---
## 1. Поиск по базе знаний
`POST /api/v1/search`
Поиск релевантных тикетов в коллекции с опциональной генерацией ответа.
### Request body
```json
{
"collection_id": "83f64913-9cb6-495e-984a-cbae31eacf54",
"query": "не могу начать смену в приложении",
"generate_answer": true
}
```
| Поле | Тип | По умолчанию | Описание |
|------------------|---------|--------------|------------------------------------|
| `collection_id` | string | — | ID коллекции |
| `query` | string | — | Поисковый запрос |
| `generate_answer`| boolean | `true` | Сгенерировать ответ LLM или нет |
### Response
```json
{
"answer": "Проверьте подключение к интернету...",
"sources": [
{
"ticket_id": "12345",
"score": 0.5885,
"category": "техподдержка",
"full_text": "Категория: техподдержка\nПроблема: ...\nРешение: ..."
}
]
}
```
| Поле | Тип | Описание |
|----------|----------------------------|----------------------------------------|
| `answer` | string или null | Сгенерированный ответ LLM или null |
| `sources`| array of SourceItem | Найденные тикеты (от 0 до 5) |
### SourceItem
| Поле | Тип | Описание |
|------------|---------|-----------------------------|
| `ticket_id`| string | ID тикета |
| `score` | float | Релевантность (0..1) |
| `category` | string | Категория тикета |
| `full_text`| string | Полный текст решения |
### Пример (curl)
```bash
curl -s -X POST http://sovet.itoservice.ru/api/v1/search \
-H "Authorization: Bearer <api-key>" \
-H "Content-Type: application/json" \
-d '{
"collection_id": "83f64913-9cb6-495e-984a-cbae31eacf54",
"query": "не могу начать смену в приложении",
"generate_answer": true
}'
```
### Пример (Python)
```python
import requests
resp = requests.post(
"http://sovet.itoservice.ru/api/v1/search",
headers={"Authorization": "Bearer <api-key>"},
json={
"collection_id": "83f64913-9cb6-495e-984a-cbae31eacf54",
"query": "не могу начать смену в приложении",
"generate_answer": True,
},
)
data = resp.json()
print(data["answer"])
```
---
## 2. Загрузка тикетов
`POST /api/v1/tickets?collection_id=<uuid>`
Загрузка массива тикетов в коллекцию. Дубликаты по `ticket_id` автоматически пропускаются.
### Request body
```json
{
"tickets": [
{
"ticket_id": 12345,
"category": "техподдержка",
"description": "Не работает принтер",
"client": "Иван",
"messages": [
{"role": "user", "text": "У меня не печатает принтер"},
{"role": "assistant", "text": "Проверьте подключение кабеля USB к компьютеру..."}
]
}
]
}
```
| Поле | Тип | По умолчанию | Описание |
|---------------|----------------------|--------------|-----------------------------|
| `ticket_id` | int или string | — | Уникальный ID тикета |
| `category` | string | `""` | Категория проблемы |
| `description` | string | `""` | Краткое описание проблемы |
| `client` | string | `""` | Имя клиента |
| `messages` | array of Message | `[]` | Переписка (user + assistant)|
### Message
```json
{"role": "user|assistant", "text": "текст сообщения"}
```
- `role``"user"` или `"assistant"`. Сообщения `"assistant"` используются как решение.
- `text` — текст сообщения. Решение должно быть длиннее 100 символов и не заканчиваться вопросительным знаком.
### Response
```json
{
"processed": 1,
"skipped": 0,
"collection_ticket_count": 100
}
```
| Поле | Тип | Описание |
|------------------------|-------|-----------------------------------|
| `processed` | int | Количество обработанных тикетов |
| `skipped` | int | Пропущено (дубликат или нет решения)|
| `collection_ticket_count`| int | Всего тикетов в коллекции |
### Почему тикет может быть пропущен (skipped)
1. **Дубликат**`ticket_id` уже существует в коллекции
2. **Нет решения** — в `messages` нет сообщения от `assistant` длиннее 100 символов
3. **Решение — вопрос** — последнее сообщение `assistant` заканчивается на `?` и короче 150 символов
4. **Решение — заглушка** — текст содержит фразы вроде «уточните», «приложите скрин», «позвоните нам» и т.п.
### Пример (curl)
```bash
curl -s -X POST 'http://sovet.itoservice.ru/api/v1/tickets?collection_id=<uuid>' \
-H "Authorization: Bearer <api-key>" \
-H "Content-Type: application/json" \
-d '{"tickets": [{"ticket_id": 1, "description": "Проблема", "messages": [{"role": "user", "text": "вопрос"}, {"role": "assistant", "text": "Проверьте соединение и перезагрузите устройство, затем повторите попытку. Если не помогает обратитесь к администратору системы."}]}]}'
```
---
## 3. Список коллекций
`GET /api/v1/collections`
### Response
```json
[
{
"id": "83f64913-9cb6-495e-984a-cbae31eacf54",
"user_id": "30939310-e3a3-4993-b1ac-10c81b751843",
"name": "OFRS",
"ticket_count": 2898,
"created_at": "2026-06-29T11:45:27.866413Z"
}
]
```
---
## 4. Профиль пользователя
`GET /api/v1/me`
### Response
```json
{
"id": "30939310-e3a3-4993-b1ac-10c81b751843",
"email": "user@example.com",
"api_key": "abc123...",
"plan": "pro",
"created_at": "2026-06-29T11:45:27.866413Z"
}
```
---
## 5. Сброс API-ключа
`PATCH /api/v1/me/api-key`
### Response
```json
{
"api_key": "новый-ключ-32-символа"
}
```
---
## 6. JWT-эндпоинты (для UI)
Эти эндпоинты требуют JWT-токен (получается через `/api/login`), а не API-ключ.
| Метод | Путь | Описание |
|-------|-------------------------------|------------------------------|
| POST | `/api/register` | Регистрация |
| POST | `/api/login` | Вход (возвращает JWT) |
| GET | `/api/me` | Профиль |
| POST | `/api/collections` | Создать коллекцию |
| GET | `/api/collections` | Список коллекций |
| GET | `/api/collections/{id}` | Информация о коллекции |
| DELETE| `/api/collections/{id}` | Удалить коллекцию |
| POST | `/api/collections/{id}/tickets` | Загрузить тикеты (JSON)|
| POST | `/api/collections/{id}/tickets/upload`| Загрузить тикеты (файл)|
| POST | `/api/search` | Поиск |
### Регистрация
```json
POST /api/register
{
"email": "user@example.com",
"password": "secret123",
"plan": "free"
}
201 {"access_token": "jwt...", "token_type": "bearer"}
```
### Логин
```json
POST /api/login
{
"email": "user@example.com",
"password": "secret123"
}
{"access_token": "jwt...", "token_type": "bearer"}
```
---
## 7. Ошибки
Все ошибки возвращают стандартный формат FastAPI:
```json
{
"detail": "Collection not found"
}
```
HTTP-статусы:
- `200` — успех
- `201` — создано
- `400` — неверный запрос
- `401` — неавторизован
- `404` — не найдено
- `429` — превышен лимит запросов (30 req/min)
- `500` — внутренняя ошибка сервера
---
## 8. Rate limiting
30 запросов в минуту на один IP-адрес. При превышении — `429 Too Many Requests`.
Лимит действует на все эндпоинты, кроме `/api/health`.
---
## 9. Health check
`GET /api/health`
```json
{"status": "ok"}
```
Не требует авторизации.