fix: Track app/models/ folder and update .gitignore

This commit is contained in:
AI Bot 2026-03-09 23:09:44 +09:00
parent b68ff82a36
commit 2a6c2300f6
3 changed files with 112 additions and 1 deletions

2
.gitignore vendored
View File

@ -3,7 +3,7 @@ __pycache__/
*.gguf
*.bin
*.pt
models/
/models/
whisper.db
data/audio/
data/samples/

74
app/models/record.py Normal file
View File

@ -0,0 +1,74 @@
"""
STT 이력 조회용 Pydantic 응답 스키마 모듈.
ORM 모델(app/db/models.py) 분리하여 API 계층의 직렬화 규격을 관리합니다.
"""
from pydantic import BaseModel, Field, ConfigDict
from typing import Optional, List
from datetime import datetime
class SegmentSchema(BaseModel):
"""TranscriptionSegment ORM → JSON 직렬화 스키마"""
model_config = ConfigDict(from_attributes=True) # Pydantic v2: ORM 객체 직렬화 허용
id: int
start_sec: float
end_sec: float
text: Optional[str]
speaker: Optional[str]
absolute_start_time: Optional[str]
absolute_end_time: Optional[str]
class RecordListResponse(BaseModel):
"""TranscriptionRecord ORM → JSON 직렬화 스키마 (세그먼트 포함)"""
model_config = ConfigDict(from_attributes=True)
id: int
filename: str
full_text: Optional[str]
language: Optional[str]
base_datetime: Optional[datetime]
processing_time_sec: Optional[float]
audio_duration_sec: Optional[float]
peak_memory_mb: Optional[float]
process_speed_x: Optional[float]
# LLM 메타데이터
title: Optional[str] = None
summary: Optional[str] = None
keywords: Optional[str] = None
urgency: Optional[str] = None
created_at: datetime
segments: List[SegmentSchema] = Field(default_factory=list)
class RecordPageResponse(BaseModel):
"""페이징이 적용된 목록 조회 응답 래퍼"""
total: int = Field(..., description="필터 조건에 해당하는 전체 레코드 수")
skip: int = Field(..., description="현재 오프셋")
limit: int = Field(..., description="현재 페이지 크기")
records: List[RecordListResponse] = Field(default_factory=list)
class DailySegmentResponse(BaseModel):
"""일자별 채팅 뷰용 세그먼트 평면 응답 스키마"""
model_config = ConfigDict(from_attributes=True)
id: int
record_id: int
start_sec: float
end_sec: float
text: Optional[str]
speaker: Optional[str]
is_reviewed: bool = False
absolute_start_time: Optional[str] = Field(None, description="ISO 8601 발화 절대 시작 시간")
absolute_end_time: Optional[str] = Field(None, description="ISO 8601 발화 절대 종료 시간")
class DailySegmentPage(BaseModel):
"""Cursor 기반 페이지네이션 래퍼 — COUNT(*) 없이 인덱스만 사용."""
items: List[DailySegmentResponse] = Field(..., description="세그먼트 목록")
next_cursor: Optional[int] = Field(None, description="다음 페이지 시작 커서 (마지막 item의 id). None이면 마지막 페이지.")
has_more: bool = Field(..., description="다음 페이지 존재 여부")

37
app/models/stt.py Normal file
View File

@ -0,0 +1,37 @@
from pydantic import BaseModel, Field
from typing import Optional, List
from datetime import datetime
class STTSegment(BaseModel):
"""발화 단위(Segment) 상세 데이터 모델"""
start_sec: float = Field(..., description="발화 시작 시간 (초)")
end_sec: float = Field(..., description="발화 종료 시간 (초)")
text: str = Field(..., description="교정이 완료된 텍스트")
speaker: Optional[str] = Field(default=None, description="휴리스틱 발화자 식별 결과")
absolute_start_time: Optional[str] = Field(default=None, description="ISO 8601 발화 시작 절대 시간")
absolute_end_time: Optional[str] = Field(default=None, description="ISO 8601 발화 종료 절대 시간")
audio_path: Optional[str] = Field(default=None, description="로컬 파일 경로 (Opus 변환본)")
id: Optional[int] = Field(default=None, description="DB segment ID (저장 후 매핑됨)")
class STTRequest(BaseModel):
"""STT 처리를 요청하기 위한 데이터 모델"""
audio_file_path: str = Field(..., description="변환할 .wav 등 오디오 파일의 절대/상대 경로")
language: str = Field(default="ko", description="오디오의 주 언어 코드 (기본값: 한국어)")
base_datetime: Optional[datetime] = Field(default=None, description="녹음 시작 절대 시간 (Line-In 동기화용)")
class STTResponse(BaseModel):
"""STT 처리 결과를 반환하기 위한 데이터 모델"""
text: str = Field(..., description="변환이 완료된 전체 문자열 텍스트")
language: str = Field(..., description="인식된/지정된 언어 코드")
segments: List[STTSegment] = Field(default_factory=list, description="개별 발화 단위 데이터 리스트")
processing_time_sec: Optional[float] = Field(default=None, description="STT 처리에 소요된 시간 (초)")
# 벤치마킹 지표
load_time_sec: Optional[float] = Field(default=None, description="모델 로드 시간 (초)")
audio_duration_sec: Optional[float] = Field(default=None, description="원본 오디오 총 길이 (초)")
peak_memory_mb: Optional[float] = Field(default=None, description="변환 중 발생한 최대 메모리 점유율 (MB)")
process_speed_x: Optional[float] = Field(default=None, description="오디오 길이 대비 처리 속도 비율 (배수)")
# 룰 기반 실시간 분석 결과
urgency: Optional[str] = Field(default="일반", description="긴급도 판별 결과")
train_number: Optional[str] = Field(default=None, description="추출된 열차 번호")