Запись аудио
Перетащите аудиофайл сюда или кликните для выбора
Поддерживаемые форматы: MP3, WAV, M4A, OGG
# app.py - Основное FastAPI приложение from fastapi import FastAPI, UploadFile, File, Form, WebSocket, WebSocketDisconnect from fastapi.responses import HTMLResponse, JSONResponse, FileResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel import whisper import openai import asyncio import json import os import tempfile import uuid import logging from typing import Optional, List from datetime import datetime from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.chains import LLMChain from langchain.prompts import PromptTemplate from langchain.chat_models import ChatOpenAI from dataclasses import dataclass import soundfile as sf import numpy as np from concurrent.futures import ThreadPoolExecutor import aiofiles # Настройка логирования logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # Модели данных class TranscriptionRequest(BaseModel): audio_data: Optional[str] = None # base64 encoded language: str = "ru" class SummaryRequest(BaseModel): text: str summary_type: str = "detailed" # detailed, brief, bullet class AudioFileRequest(BaseModel): filename: str content_type: str # Конфигурация @dataclass class Config: WHISPER_MODEL_SIZE = "base" OPENAI_API_KEY = os.getenv("OPENAI_API_KEY", "") SAMPLE_RATE = 16000 CHUNK_SIZE = 1024 MAX_FILE_SIZE = 50 * 1024 * 1024 # 50MB # Пути UPLOAD_FOLDER = "uploads" STATIC_FOLDER = "static" TEMPLATES_FOLDER = "templates" # Создание директорий os.makedirs(Config.UPLOAD_FOLDER, exist_ok=True) os.makedirs(Config.STATIC_FOLDER, exist_ok=True) os.makedirs(Config.TEMPLATES_FOLDER, exist_ok=True) # Инициализация приложения app = FastAPI( title="Audio to Summary AI", description="Веб-приложение для преобразования звука в текст и создания конспектов", version="1.0.0" ) # CORS middleware app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Монтирование статических файлов app.mount("/static", StaticFiles(directory=Config.STATIC_FOLDER), name="static") templates = Jinja2Templates(directory=Config.TEMPLATES_FOLDER) # Глобальные переменные whisper_model = None llm_chain = None executor = ThreadPoolExecutor(max_workers=4) # Инициализация моделей async def init_models(): """Инициализация AI моделей""" global whisper_model, llm_chain logger.info("Инициализация моделей...") # Загрузка Whisper модели try: whisper_model = whisper.load_model(Config.WHISPER_MODEL_SIZE) logger.info(f"Whisper модель '{Config.WHISPER_MODEL_SIZE}' загружена") except Exception as e: logger.error(f"Ошибка загрузки Whisper: {e}") # Инициализация LangChain для конспектов if Config.OPENAI_API_KEY: try: llm = ChatOpenAI( openai_api_key=Config.OPENAI_API_KEY, model_name="gpt-3.5-turbo", temperature=0.3, max_tokens=1000 ) prompt_template = PromptTemplate( input_variables=["text", "summary_type"], template=""" На основе предоставленного текста создай конспект следующего типа: {summary_type} Варианты типов: - detailed: Детальный структурированный конспект с разделами - brief: Краткое изложение (3-5 предложений) - bullet: Маркированный список ключевых пунктов Текст: {text} Конспект: """ ) llm_chain = LLMChain(llm=llm, prompt=prompt_template) logger.info("LangChain модель инициализирована") except Exception as e: logger.error(f"Ошибка инициализации LangChain: {e}") else: logger.warning("OPENAI_API_KEY не установлен, функция конспектов отключена") @app.on_event("startup") async def startup_event(): """Запуск при старте приложения""" await init_models() # WebSocket для реального времени class ConnectionManager: def __init__(self): self.active_connections: List[WebSocket] = [] async def connect(self, websocket: WebSocket): await websocket.accept() self.active_connections.append(websocket) def disconnect(self, websocket: WebSocket): self.active_connections.remove(websocket) async def send_personal_message(self, message: str, websocket: WebSocket): await websocket.send_text(message) async def broadcast(self, message: str): for connection in self.active_connections: await connection.send_text(message) manager = ConnectionManager() # Вспомогательные функции def save_audio_file(file_content: bytes, extension: str = "wav") -> str: """Сохранение аудиофайла""" filename = f"{uuid.uuid4()}.{extension}" filepath = os.path.join(Config.UPLOAD_FOLDER, filename) with open(filepath, "wb") as f: f.write(file_content) return filepath def transcribe_audio(audio_path: str, language: str = "ru") -> str: """Транскрибирование аудио с помощью Whisper""" try: result = whisper_model.transcribe( audio_path, language=language, fp16=False, task="transcribe" ) return result["text"] except Exception as e: logger.error(f"Ошибка транскрибирования: {e}") raise def generate_summary(text: str, summary_type: str = "detailed") -> str: """Генерация конспекта""" if not llm_chain: raise ValueError("LLM модель не инициализирована. Проверьте OPENAI_API_KEY.") try: # Разбиваем текст если он слишком длинный text_splitter = RecursiveCharacterTextSplitter( chunk_size=3000, chunk_overlap=200, length_function=len, ) chunks = text_splitter.split_text(text) if len(chunks) == 1: result = llm_chain.run(text=text, summary_type=summary_type) return result else: # Обрабатываем каждый чанк и объединяем результаты summaries = [] for chunk in chunks: summary = llm_chain.run(text=chunk, summary_type=summary_type) summaries.append(summary) # Объединяем все конспекты combined_summary = "\n\n".join(summaries) # Создаем финальный обобщенный конспект final_summary = llm_chain.run( text=combined_summary, summary_type="brief" ) return final_summary except Exception as e: logger.error(f"Ошибка генерации конспекта: {e}") raise # API endpoints @app.get("/", response_class=HTMLResponse) async def read_root(): """Главная страница""" html_content = """
Преобразуйте речь в текст и создавайте интеллектуальные конспекты
Перетащите аудиофайл сюда или кликните для выбора
Поддерживаемые форматы: MP3, WAV, M4A, OGG