mirror of
https://github.com/hwanny1128/HGZero.git
synced 2025-12-06 13:46:24 +00:00
138 lines
6.2 KiB
Python
138 lines
6.2 KiB
Python
"""
|
|
관련자료 데이터 모델
|
|
"""
|
|
from typing import Optional, List, Dict, Any
|
|
from datetime import datetime
|
|
from pydantic import BaseModel, Field
|
|
from uuid import UUID
|
|
|
|
|
|
class DocumentMetadata(BaseModel):
|
|
"""문서 메타데이터"""
|
|
folder: Optional[str] = Field(None, description="폴더명")
|
|
business_domain: Optional[str] = Field(None, description="업무 도메인")
|
|
additional_fields: Optional[Dict[str, Any]] = Field(None, description="추가 필드")
|
|
|
|
|
|
class Document(BaseModel):
|
|
"""문서 모델"""
|
|
document_id: str = Field(..., description="문서 ID")
|
|
document_type: str = Field(..., description="문서 타입 (meeting_minutes, org_document 등)")
|
|
business_domain: Optional[str] = Field(None, description="업무 도메인")
|
|
title: str = Field(..., description="문서 제목")
|
|
content: str = Field(..., description="문서 전체 내용")
|
|
summary: str = Field(..., description="문서 요약 (3-5 문장)")
|
|
keywords: List[str] = Field(default_factory=list, description="키워드 목록")
|
|
created_date: Optional[str] = Field(None, description="생성일시")
|
|
participants: List[str] = Field(default_factory=list, description="참석자 목록 (회의록의 경우)")
|
|
metadata: Optional[DocumentMetadata] = Field(None, description="메타데이터")
|
|
embedding: Optional[List[float]] = Field(None, description="임베딩 벡터 (1536차원)")
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"document_id": "고객-MM-001",
|
|
"document_type": "meeting_minutes",
|
|
"business_domain": "고객서비스",
|
|
"title": "상담 품질 향상 워크샵 1차",
|
|
"content": "회의 일시: 2025-10-02...",
|
|
"summary": "고객 만족도 지표 검토와 VOC 트렌드 분석을 논의...",
|
|
"keywords": ["CSAT", "고객응대", "챗봇"],
|
|
"participants": ["김민준", "이미준"]
|
|
}
|
|
}
|
|
|
|
|
|
class DocumentChunk(BaseModel):
|
|
"""문서 청크 (Azure AI Search 인덱싱용)"""
|
|
id: str = Field(..., description="청크 ID (document_id_chunk_N)")
|
|
document_id: str = Field(..., description="원본 문서 ID")
|
|
document_type: str = Field(..., description="문서 타입")
|
|
title: str = Field(..., description="문서 제목")
|
|
folder: Optional[str] = Field(None, description="폴더명")
|
|
created_date: Optional[str] = Field(None, description="생성일시")
|
|
participants: List[str] = Field(default_factory=list, description="참석자 목록")
|
|
keywords: List[str] = Field(default_factory=list, description="키워드 목록")
|
|
agenda_id: Optional[str] = Field(None, description="안건 ID (회의록의 경우)")
|
|
agenda_title: Optional[str] = Field(None, description="안건 제목")
|
|
chunk_index: int = Field(..., description="청크 인덱스")
|
|
content: str = Field(..., description="청크 내용")
|
|
content_vector: List[float] = Field(..., description="내용 임베딩 벡터")
|
|
token_count: int = Field(..., description="토큰 수")
|
|
|
|
|
|
class DocumentSearchRequest(BaseModel):
|
|
"""문서 검색 요청"""
|
|
query: str = Field(..., min_length=1, description="검색 쿼리")
|
|
top_k: int = Field(3, ge=1, le=10, description="반환할 최대 결과 수")
|
|
relevance_threshold: float = Field(0.70, ge=0.0, le=1.0, description="최소 관련도 임계값")
|
|
folder: Optional[str] = Field(None, description="폴더 필터 (같은 폴더 우선)")
|
|
document_type: Optional[str] = Field(None, description="문서 타입 필터")
|
|
business_domain: Optional[str] = Field(None, description="업무 도메인 필터")
|
|
semantic_ranking: bool = Field(True, description="Semantic Ranking 사용 여부")
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"query": "고객 만족도 개선 방안",
|
|
"top_k": 3,
|
|
"relevance_threshold": 0.70,
|
|
"folder": "고객서비스팀",
|
|
"semantic_ranking": True
|
|
}
|
|
}
|
|
|
|
|
|
class DocumentSearchResult(BaseModel):
|
|
"""문서 검색 결과"""
|
|
document_id: str
|
|
title: str
|
|
document_type: str
|
|
created_date: Optional[str]
|
|
relevance_score: float = Field(..., ge=0.0, le=1.0)
|
|
relevance_level: str = Field(..., description="HIGH (>90%), MEDIUM (70-90%), LOW (<70%)")
|
|
content_excerpt: str = Field(..., description="관련 내용 발췌")
|
|
folder: Optional[str] = None
|
|
|
|
|
|
class RelatedMeetingRequest(BaseModel):
|
|
"""관련 회의록 검색 요청"""
|
|
meeting_id: str = Field(..., description="현재 회의 ID")
|
|
top_k: int = Field(3, ge=1, le=5, description="반환할 최대 결과 수")
|
|
relevance_threshold: float = Field(0.70, ge=0.0, le=1.0, description="최소 관련도 임계값")
|
|
|
|
|
|
class RelatedMeeting(BaseModel):
|
|
"""관련 회의록"""
|
|
meeting_id: str
|
|
title: str
|
|
meeting_date: Optional[str]
|
|
relevance_score: float = Field(..., ge=0.0, le=1.0)
|
|
relevance_level: str = Field(..., description="HIGH, MEDIUM, LOW")
|
|
similar_content_summary: Optional[str] = Field(None, description="유사 내용 요약 (3문장)")
|
|
url: str = Field(..., description="회의록 URL")
|
|
|
|
|
|
class DocumentSummarizeRequest(BaseModel):
|
|
"""문서 요약 요청"""
|
|
document_id: str = Field(..., description="문서 ID")
|
|
current_meeting_id: Optional[str] = Field(None, description="현재 회의 ID (비교용)")
|
|
summary_type: str = Field("similar_content", description="요약 타입 (similar_content, full)")
|
|
|
|
|
|
class DocumentSummary(BaseModel):
|
|
"""문서 요약"""
|
|
document_id: str
|
|
summary: str = Field(..., description="요약 내용")
|
|
generated_by: str = Field("claude-3-5-sonnet", description="생성 모델")
|
|
tokens_used: int = Field(..., description="사용된 토큰 수")
|
|
cached: bool = Field(False, description="캐시 여부")
|
|
|
|
|
|
class DocumentStats(BaseModel):
|
|
"""문서 통계"""
|
|
total_documents: int = Field(..., description="전체 문서 수")
|
|
by_type: Dict[str, int] = Field(..., description="타입별 문서 수")
|
|
by_domain: Dict[str, int] = Field(..., description="도메인별 문서 수")
|
|
total_chunks: int = Field(..., description="전체 청크 수")
|