Представьте: вы руководитель отдела продаж. Каждый день десятки звонков, сотни минут разговоров. Как понять, кто из менеджеров работает качественно, а кого пора отправлять на переобучение?
Раньше приходилось выборочно слушать записи — это занимало часы. Я решил автоматизировать процесс и собрал систему, которая:
speechkit-agentai.speechkit-stt.user и ai.languageModels.userYANDEX_API_KEY и YANDEX_FOLDER_IDhttps://ваш_сервер:8000/webhook/mangocallId, recordUrl, callerNumber, durationСоздайте logger.py, чтобы проверить структуру вебхука:
from fastapi import FastAPI, Request
import json
import logging
from datetime import datetime
app = FastAPI()
logging.basicConfig(level=logging.INFO)
@app.post("/webhook/mango")
async def logger(request: Request):
data = await request.json()
logging.info(json.dumps(data, indent=2, ensure_ascii=False))
with open("webhook_log.txt", "a", encoding="utf-8") as f:
f.write(json.dumps(data, indent=2, ensure_ascii=False))
return {"status": "ok"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
Запустите: python3 logger.py и сделайте тестовый звонок.
{"webhookType":2,"callId":123,"recordUrl":"https://...","duration":300,...}Этот скрипт принимает вебхуки, запускает AI-анализ и пересылает копию в старую 1С.
from fastapi import FastAPI, Request
import httpx
import asyncio
app = FastAPI()
OLD_1C_URL = "https://37.230.154.96:88/logo_test/hs/MangoAPI/v1/"
async def run_ai(mango_data):
print(f"🤖 AI: Анализирую звонок {mango_data.get('callId')}")
# 🔥 Сюда вставляете вызов вашего AI-агента
@app.post("/webhook/mango")
async def dispatcher(request: Request):
data = await request.json()
if data.get('webhookType') == 2 and data.get('recordUrl'):
asyncio.create_task(run_ai(data))
async with httpx.AsyncClient() as client:
await client.post(OLD_1C_URL, json=data, timeout=30.0)
return {"status": "ok"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
Важно: замените OLD_1C_URL на свой адрес.
Полный код агента (agent.py):
import os
import requests
import json
import re
from dotenv import load_dotenv
load_dotenv()
YANDEX_API_KEY = os.getenv("YANDEX_API_KEY")
YANDEX_FOLDER_ID = os.getenv("YANDEX_FOLDER_ID")
def transcribe(audio_content):
url = "https://stt.api.cloud.yandex.net/speech/v1/stt:recognize"
headers = {"Authorization": f"Api-Key {YANDEX_API_KEY}", "Content-Type": "audio/ogg;codecs=opus"}
resp = requests.post(url, headers=headers, data=audio_content, timeout=60)
return resp.json().get("result") if resp.status_code == 200 else None
def analyze_gpt(transcript):
url = "https://llm.api.cloud.yandex.net/foundationModels/v1/completion"
prompt = """Ты эксперт по оценке сервиса. Верни ТОЛЬКО JSON:
{"manager_rating": число 1-5, "verdict": "НОРМ" или "ТОКСИЧЕН", "verdict_reason": "причина", "emotional_tone": "positive/neutral/negative"}
Диалог: """ + transcript
payload = {
"modelUri": f"gpt://{YANDEX_FOLDER_ID}/yandexgpt-lite",
"completionOptions": {"temperature": 0.3, "maxTokens": 1000},
"messages": [{"role": "user", "text": prompt}]
}
headers = {"Authorization": f"Api-Key {YANDEX_API_KEY}", "Content-Type": "application/json"}
resp = requests.post(url, headers=headers, json=payload, timeout=60)
if resp.status_code == 200:
text = resp.json().get("result", {}).get("alternatives", [{}])[0].get("message", {}).get("text", "")
match = re.search(r'\{.*\}', text, re.DOTALL)
if match:
return json.loads(match.group())
return {"manager_rating":0,"verdict":"ОШИБКА","verdict_reason":"Ошибка анализа","emotional_tone":"unknown"}
def process_call(call_data):
audio = requests.get(call_data["recordUrl"], timeout=30).content
transcript = transcribe(audio)
if not transcript:
return None
return analyze_gpt(transcript)
Файл .env:
YANDEX_API_KEY=ваш_ключ
YANDEX_FOLDER_ID=ваш_folder_id
DATABASE_URL=sqlite:///calls.db
Добавьте в main.py эндпоинты для API:
@app.get("/api/calls")
def get_calls():
session = Session()
calls = session.query(Call).order_by(Call.created_at.desc()).limit(100).all()
return [{"call_id":c.call_id,"verdict":c.verdict,"manager_rating":c.manager_rating,"created_at":c.created_at.isoformat()} for c in calls]
@app.get("/api/statistics")
def stats():
session = Session()
total = session.query(Call).count()
toxic = session.query(Call).filter_by(verdict="ТОКСИЧЕН").count()
return {"total":total,"toxic":toxic,"norm":total-toxic,"toxic_percent":round(toxic/total*100,1) if total else 0}
Создайте index.html — он будет загружать данные через эти API и показывать таблицу.
| Услуга | Стоимость | Примечание |
|---|---|---|
| Mango Office | 0 ₽ | Уже оплачено |
| Yandex SpeechKit | ~1 200–2 400 ₽ | 0,40–0,80 ₽/мин |
| YandexGPT | ~100–200 ₽ | За 100 звонков |
| Сервер VPS | ~500–800 ₽ | Базовый тариф |
| ИТОГО | ~1 800 – 3 400 ₽ | За 100 звонков |
Теперь вы в любой момент можете зайти в веб-интерфейс и увидеть, кто из менеджеров «токсичит», какой средний рейтинг и динамику качества по дням.
Комментарии
Пока нет комментариев. Будьте первым!