File size: 10,823 Bytes
065853d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
"""
OpenAI API 라우터
GPT-4 관련 엔드포인트들 (채팅, 감정분석 등)
"""

from fastapi import APIRouter, HTTPException, Depends, status
from typing import List, Dict, Any
from loguru import logger

from ..services.openai_client import get_openai_client
from ..models.function_models import (
    OpenAICompletionRequest, OpenAICompletionResponse,
    EmotionAnalysisRequest, EmotionAnalysisResponse,
    ChatMessage, SystemHealthCheck
)


router = APIRouter()


@router.post("/completion", response_model=OpenAICompletionResponse)
async def create_completion(
    request: OpenAICompletionRequest,
    openai_client = Depends(get_openai_client)
):
    """
    🤖 GPT-4 채팅 완성 생성

    - 일반적인 GPT-4 채팅 완성
    - 사용자 정의 모델, 온도, 토큰 수 설정 가능
    - 스트리밍 지원 (선택적)
    """
    try:
        logger.info(f"GPT-4 완성 요청 - 모델: {request.model}, 메시지 수: {len(request.messages)}")

        # ChatMessage를 dict로 변환
        messages = [
            {"role": msg.role.value, "content": msg.content}
            for msg in request.messages
        ]

        response = await openai_client.create_completion(
            messages=messages,
            model=request.model,
            temperature=request.temperature,
            max_tokens=request.max_tokens,
            top_p=request.top_p
        )

        return response

    except Exception as e:
        logger.error(f"GPT-4 완성 생성 실패: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"GPT-4 완성 생성 중 오류가 발생했습니다: {str(e)}"
        )


@router.post("/teen-empathy", response_model=str)
async def create_teen_empathy_response(
    user_message: str,
    conversation_history: List[ChatMessage] = None,
    context_info: str = None,
    openai_client = Depends(get_openai_client)
):
    """
    💙 청소년 공감형 응답 생성

    - 청소년 전용 공감 시스템 프롬프트 적용
    - 대화 히스토리 및 맥락 정보 활용
    - 따뜻하고 지지적인 응답 생성
    """
    try:
        logger.info(f"청소년 공감 응답 요청: '{user_message[:50]}...'")

        response = await openai_client.create_teen_empathy_response(
            user_message=user_message,
            conversation_history=conversation_history,
            context_info=context_info
        )

        return response

    except Exception as e:
        logger.error(f"청소년 공감 응답 생성 실패: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"청소년 공감 응답 생성 중 오류가 발생했습니다: {str(e)}"
        )


@router.post("/analyze-emotion", response_model=EmotionAnalysisResponse)
async def analyze_emotion(
    request: EmotionAnalysisRequest,
    openai_client = Depends(get_openai_client)
):
    """
    🎭 감정 및 맥락 분석

    - 텍스트에서 주요 감정 추출
    - 관계 맥락 파악 (부모님, 친구, 형제자매 등)
    - 적절한 공감 전략 추천
    """
    try:
        logger.info(f"감정 분석 요청: '{request.text[:50]}...'")

        response = await openai_client.analyze_emotion_and_context(
            text=request.text,
            additional_context=request.context
        )

        return response

    except Exception as e:
        logger.error(f"감정 분석 실패: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"감정 분석 중 오류가 발생했습니다: {str(e)}"
        )


@router.post("/react-response")
async def generate_react_response(
    user_message: str,
    similar_contexts: List[Dict[str, Any]] = None,
    emotion: str = None,
    relationship: str = None,
    openai_client = Depends(get_openai_client)
):
    """
    🧠 ReAct 패턴 응답 생성

    - Thought → Action → Observation → Response
    - 단계별 추론 과정 포함
    - 유사 맥락 정보 활용
    """
    try:
        logger.info(f"ReAct 응답 요청: '{user_message[:50]}...'")

        response_text, react_steps = await openai_client.generate_react_response(
            user_message=user_message,
            similar_contexts=similar_contexts or [],
            emotion=emotion,
            relationship=relationship
        )

        return {
            "response": response_text,
            "react_steps": react_steps,
            "metadata": {
                "emotion": emotion,
                "relationship": relationship,
                "context_count": len(similar_contexts) if similar_contexts else 0
            }
        }

    except Exception as e:
        logger.error(f"ReAct 응답 생성 실패: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"ReAct 응답 생성 중 오류가 발생했습니다: {str(e)}"
        )


@router.get("/models")
async def list_available_models():
    """
    📋 사용 가능한 모델 목록

    - 지원하는 OpenAI 모델들
    - 각 모델의 특징 및 사용 권장사항
    """
    return {
        "available_models": [
            {
                "name": "gpt-4",
                "description": "가장 강력한 모델, 복잡한 추론에 최적",
                "recommended_for": ["청소년 공감 상담", "복잡한 맥락 이해"],
                "max_tokens": 8192,
                "cost": "높음"
            },
            {
                "name": "gpt-4-turbo",
                "description": "빠르고 효율적인 GPT-4 버전",
                "recommended_for": ["실시간 채팅", "일반적인 상담"],
                "max_tokens": 128000,
                "cost": "중간"
            },
            {
                "name": "gpt-3.5-turbo",
                "description": "빠르고 경제적인 모델",
                "recommended_for": ["간단한 질문", "테스트용"],
                "max_tokens": 4096,
                "cost": "낮음"
            }
        ],
        "current_default": "gpt-4",
        "recommendation": "청소년 공감형 상담에는 gpt-4를 권장합니다"
    }


@router.get("/health", response_model=SystemHealthCheck)
async def openai_health_check(openai_client = Depends(get_openai_client)):
    """
    💊 OpenAI 서비스 헬스 체크

    - API 연결 상태 확인
    - 응답 시간 측정
    - 서비스 가용성 점검
    """
    try:
        import time
        start_time = time.time()

        # 간단한 테스트 요청으로 연결 확인
        test_response = await openai_client.create_completion(
            messages=[{"role": "user", "content": "Hello"}],
            max_tokens=5,
            temperature=0
        )

        response_time_ms = (time.time() - start_time) * 1000

        return SystemHealthCheck(
            status="healthy",
            services={
                "openai_api": True,
                "gpt4_model": True,
                "embedding_generation": True
            },
            response_time_ms=response_time_ms,
            version="1.0.0"
        )

    except Exception as e:
        logger.error(f"OpenAI 헬스 체크 실패: {e}")
        return SystemHealthCheck(
            status="unhealthy",
            services={
                "openai_api": False,
                "gpt4_model": False,
                "embedding_generation": False
            },
            response_time_ms=0.0,
            version="1.0.0"
        )


@router.get("/usage-stats")
async def get_usage_stats():
    """
    📊 OpenAI API 사용 통계

    - 토큰 사용량 추정
    - 비용 관련 정보
    """
    return {
        "current_session": {
            "requests_made": "실시간 추적 필요",
            "tokens_used": "실시간 추적 필요",
            "estimated_cost": "실시간 추적 필요"
        },
        "cost_info": {
            "gpt-4": {
                "input_per_1k_tokens": "$0.03",
                "output_per_1k_tokens": "$0.06"
            },
            "gpt-4-turbo": {
                "input_per_1k_tokens": "$0.01",
                "output_per_1k_tokens": "$0.03"
            },
            "gpt-3.5-turbo": {
                "input_per_1k_tokens": "$0.0015",
                "output_per_1k_tokens": "$0.002"
            }
        },
        "optimization_tips": [
            "적절한 max_tokens 설정으로 비용 절약",
            "간단한 작업은 gpt-3.5-turbo 사용",
            "시스템 프롬프트 최적화로 토큰 절약",
            "불필요한 대화 히스토리 제거"
        ]
    }


@router.post("/test-empathy")
async def test_empathy_response(
    test_message: str = "친구가 나를 무시하는 것 같아서 기분이 나빠",
    openai_client = Depends(get_openai_client)
):
    """
    🧪 공감형 응답 테스트

    - 청소년 공감형 시스템의 응답 품질 테스트
    - 다양한 테스트 케이스 제공
    """
    try:
        # 감정 분석
        emotion_result = await openai_client.analyze_emotion_and_context(test_message)

        # 공감형 응답 생성
        empathy_response = await openai_client.create_teen_empathy_response(test_message)

        # ReAct 응답 생성
        react_response, react_steps = await openai_client.generate_react_response(
            user_message=test_message,
            emotion=emotion_result.primary_emotion.value,
            relationship=emotion_result.relationship_context.value if emotion_result.relationship_context else None
        )

        return {
            "test_input": test_message,
            "emotion_analysis": {
                "primary_emotion": emotion_result.primary_emotion.value,
                "confidence": emotion_result.emotion_confidence,
                "relationship": emotion_result.relationship_context.value if emotion_result.relationship_context else None,
                "strategies": [s.value for s in emotion_result.recommended_strategies]
            },
            "empathy_response": empathy_response,
            "react_response": {
                "response": react_response,
                "steps": react_steps
            },
            "test_info": {
                "response_quality": "수동 평가 필요",
                "empathy_level": "수동 평가 필요",
                "actionability": "수동 평가 필요"
            }
        }

    except Exception as e:
        logger.error(f"공감 응답 테스트 실패: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"테스트 실행 중 오류가 발생했습니다: {str(e)}"
        )