Бэкенд:
- TicketInput: ticket_id принимает int | str, приводится к str (было 500 на числовых ID)
- LLM: добавлен импорт logger, обработка 429 и не-200 ответов от OpenRouter
- Смена модели на poolside/laguna-m.1:free (обход лимитов OpenRouter)
- Добавлен GET /api/collections/{id} — получение коллекции по ID
- Дедикат заявок: hash() заменён на детерминированный hashlib.md5
для ID точек в Qdrant (раньше после рестарта пода создавались дубликаты)
- Добавлена get_existing_ticket_ids() — проверка дубликатов до эмбеддинга,
пропуск уже загруженных заявок
- Мультитенантная изоляция: tenant_id + collection_id во всех фильтрах Qdrant
- Эмбеддинги: заменён несовместимый openai SDK на прямой httpx
- Реренкинг: исправлен доступ к ScoredPoint.payload через .get()
- Чанкинг: расширены роли (support/operator/agent + client/user/customer)
- bcrypt: понижен до 4.0.1 (5.x несовместим с passlib)
Фронтенд:
- Регистрация: добавлен выбор тарифа (free/starter/pro)
- CollectionView: ticket_count загружается с бэкенда при монтировании
(раньше жил только в React-состоянии — сбрасывался после обновления страницы)
- uploadFile: используется getToken() вместо устаревшей переменной token,
в ошибке показывается реальный HTTP-статус
- Nginx: увеличен client_max_body_size до 50M для загрузки файлов
- k8s: добавлены манифесты namespace, postgres, redis, qdrant, backend,
frontend, ingress, traefik
30 lines
1.4 KiB
Python
30 lines
1.4 KiB
Python
import urllib.request, json
|
|
|
|
data = json.dumps({'email':'testplan@test.ru','password':'test123'}).encode()
|
|
req = urllib.request.Request('http://localhost:8000/api/login', data=data, headers={'Content-Type':'application/json'}, method='POST')
|
|
r = json.loads(urllib.request.urlopen(req).read())
|
|
token = r['access_token']
|
|
print('1. Login OK')
|
|
|
|
# Upload via multipart
|
|
boundary = '----TestBoundary123'
|
|
body_parts = []
|
|
body_parts.append('--' + boundary)
|
|
body_parts.append('Content-Disposition: form-data; name="file"; filename="test.json"')
|
|
body_parts.append('Content-Type: application/json')
|
|
body_parts.append('')
|
|
body_parts.append(json.dumps([{'ticket_id':'T-002','category':'network','description':'Network down','client':'Petr','messages':[{'role':'client','text':'internet not working'},{'role':'support','text':'try rebooting the router'}]}]))
|
|
body_parts.append('--' + boundary + '--')
|
|
body_parts.append('')
|
|
body = '\r\n'.join(body_parts).encode()
|
|
|
|
headers = {
|
|
'Content-Type': 'multipart/form-data; boundary=' + boundary,
|
|
'Authorization': 'Bearer ' + token,
|
|
}
|
|
req = urllib.request.Request('http://localhost:8000/api/collections/9756bf5f-a89d-424d-bd73-ff4ad839ae4b/tickets/upload', data=body, headers=headers, method='POST')
|
|
try:
|
|
resp = json.loads(urllib.request.urlopen(req).read().decode())
|
|
print('2. Upload OK:', resp)
|
|
except urllib.error.HTTPError as e:
|
|
print('2. Upload error:', e.code, e.read().decode())
|