import gradio as gr import os import requests import json import time from dotenv import load_dotenv # .env 파일 로드 (있는 경우) load_dotenv() def create_deepseek_interface(): # 환경 변수에서 API 키 가져오기 api_key = os.getenv("FW_API_KEY") if not api_key: print("경고: FW_API_KEY 환경 변수가 설정되지 않았습니다.") # 스트리밍 방식으로 DeepSeek API 호출 함수 def query_deepseek_streaming(message, history): if not api_key: yield history, "환경 변수 FW_API_KEY가 설정되지 않았습니다. 서버에서 환경 변수를 확인해주세요." return # API 요청을 위한 대화 기록 준비 messages = [] for user, assistant in history: messages.append({"role": "user", "content": user}) messages.append({"role": "assistant", "content": assistant}) # 새 사용자 메시지 추가 messages.append({"role": "user", "content": message}) # API 요청 준비 url = "https://api.fireworks.ai/inference/v1/chat/completions" payload = { "model": "accounts/fireworks/models/deepseek-v3-0324", "max_tokens": 20480, "top_p": 1, "top_k": 40, "presence_penalty": 0, "frequency_penalty": 0, "temperature": 0.6, "messages": messages, "stream": True # 스트리밍 활성화 } headers = { "Accept": "application/json", "Content-Type": "application/json", "Authorization": f"Bearer {api_key}" } try: # 스트리밍 응답 요청 response = requests.request("POST", url, headers=headers, data=json.dumps(payload), stream=True) response.raise_for_status() # HTTP 오류 발생 시 예외 발생 # 메시지를 추가하고 초기 빈 응답으로 시작 new_history = history.copy() new_history.append((message, "")) # 응답 전체 텍스트 full_response = "" # 스트리밍 응답 처리 for line in response.iter_lines(): if line: line_text = line.decode('utf-8') # 'data: ' 접두사 제거 if line_text.startswith("data: "): line_text = line_text[6:] # 스트림 종료 메시지 확인 if line_text == "[DONE]": break try: # JSON 파싱 chunk = json.loads(line_text) chunk_content = chunk.get("choices", [{}])[0].get("delta", {}).get("content", "") if chunk_content: full_response += chunk_content # 채팅 기록 업데이트 new_history[-1] = (message, full_response) yield new_history, "" except json.JSONDecodeError: continue # 최종 응답 반환 yield new_history, "" except requests.exceptions.RequestException as e: error_msg = f"API 오류: {str(e)}" if hasattr(e, 'response') and e.response and e.response.status_code == 401: error_msg = "인증 실패. 환경 변수 FW_API_KEY를 확인해주세요." yield history, error_msg # Gradio 인터페이스 생성 with gr.Blocks(theme="soft", fill_height=True) as demo: # 헤더 섹션 gr.Markdown( """ # 🤖 DeepSeek V3 스트리밍 인터페이스 ### Fireworks AI가 제공하는 고급 AI 모델 - 실시간 응답 지원 """ ) # 메인 레이아웃 (두 개의 열) with gr.Row(): # 사이드바 - 모델 정보 with gr.Column(scale=1): gr.Markdown( """ ## 📊 모델 세부 정보 - **모델**: DeepSeek-V3-0324 - **제공자**: Fireworks AI - **최대 토큰**: 20,480 - **온도**: 0.6 - **기능**: 고급 언어 이해와 실시간 스트리밍 응답 > **참고**: API 키는 환경 변수(FW_API_KEY)에서 자동으로 로드됩니다. """ ) # 오류 메시지 표시 error_box = gr.Markdown("") # 메인 콘텐츠 영역 with gr.Column(scale=2): # 채팅 인터페이스 chatbot = gr.Chatbot( height=500, show_label=False, container=True, bubble=True, avatar_images=("👤", "🤖") ) # 입력 영역 with gr.Row(): msg = gr.Textbox( label="메시지", placeholder="여기에 프롬프트를 입력하세요...", show_label=False, scale=9 ) submit = gr.Button("전송", variant="primary", scale=1) # 대화 초기화 버튼 with gr.Row(): clear = gr.ClearButton([msg, chatbot], value="🧹 대화 초기화") # 예제 쿼리 gr.Examples( examples=[ "딥러닝에서 트랜스포머와 RNN의 차이점을 설명해주세요.", "특정 범위 내의 소수를 찾는 파이썬 함수를 작성해주세요.", "강화학습의 주요 개념을 요약해주세요." ], inputs=msg ) # 버튼과 기능 연결 submit.click( query_deepseek_streaming, inputs=[msg, chatbot], outputs=[chatbot, error_box] ).then( lambda: "", None, [msg] ) # Enter 키 제출 허용 msg.submit( query_deepseek_streaming, inputs=[msg, chatbot], outputs=[chatbot, error_box] ).then( lambda: "", None, [msg] ) return demo # 인터페이스 실행 if __name__ == "__main__": demo = create_deepseek_interface() demo.launch(debug=True)