Sazid2 commited on
Commit
43c531f
·
verified ·
1 Parent(s): 56a2ec1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +121 -9
app.py CHANGED
@@ -1,11 +1,16 @@
1
- from fastapi import FastAPI
2
  from fastapi.middleware.cors import CORSMiddleware
 
3
  from pydantic import BaseModel
4
  import requests
5
  import os
 
 
 
6
 
7
  DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
8
  DEEPSEEK_URL = "https://api.deepseek.com/chat/completions"
 
9
 
10
  app = FastAPI()
11
 
@@ -17,15 +22,45 @@ app.add_middleware(
17
  allow_headers=["*"],
18
  )
19
 
 
 
 
 
20
  class AskRequest(BaseModel):
21
- messages: list
 
 
 
22
 
23
  @app.get("/")
24
  def health():
25
- return {"status": "HF DeepSeek backend running"}
26
 
27
  @app.post("/ask")
28
  def ask(req: AskRequest):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  headers = {
30
  "Content-Type": "application/json",
31
  "Authorization": f"Bearer {DEEPSEEK_API_KEY}"
@@ -33,13 +68,90 @@ def ask(req: AskRequest):
33
 
34
  payload = {
35
  "model": "deepseek-chat",
36
- "messages": req.messages,
37
- "temperature": 0.2
 
38
  }
39
 
40
- r = requests.post(DEEPSEEK_URL, headers=headers, json=payload, timeout=60)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
- if r.status_code != 200:
43
- return {"error": "DeepSeek API failed", "detail": r.text}
 
 
 
 
 
 
 
44
 
45
- return r.json()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, HTTPException
2
  from fastapi.middleware.cors import CORSMiddleware
3
+ from fastapi.responses import StreamingResponse
4
  from pydantic import BaseModel
5
  import requests
6
  import os
7
+ import json
8
+ import asyncio
9
+ from typing import List, Dict, Any
10
 
11
  DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
12
  DEEPSEEK_URL = "https://api.deepseek.com/chat/completions"
13
+ DEEPSEEK_STREAM_URL = "https://api.deepseek.com/chat/completions"
14
 
15
  app = FastAPI()
16
 
 
22
  allow_headers=["*"],
23
  )
24
 
25
+ class Message(BaseModel):
26
+ role: str
27
+ content: str
28
+
29
  class AskRequest(BaseModel):
30
+ messages: List[Message]
31
+
32
+ class StreamRequest(BaseModel):
33
+ messages: List[Message]
34
 
35
  @app.get("/")
36
  def health():
37
+ return {"status": "HF DeepSeek backend running with streaming support"}
38
 
39
  @app.post("/ask")
40
  def ask(req: AskRequest):
41
+ """Non-streaming endpoint for backward compatibility"""
42
+ headers = {
43
+ "Content-Type": "application/json",
44
+ "Authorization": f"Bearer {DEEPSEEK_API_KEY}"
45
+ }
46
+
47
+ payload = {
48
+ "model": "deepseek-chat",
49
+ "messages": [msg.dict() for msg in req.messages],
50
+ "temperature": 0.2,
51
+ "stream": False
52
+ }
53
+
54
+ try:
55
+ r = requests.post(DEEPSEEK_URL, headers=headers, json=payload, timeout=60)
56
+ r.raise_for_status()
57
+ return r.json()
58
+ except requests.exceptions.RequestException as e:
59
+ raise HTTPException(status_code=500, detail=f"DeepSeek API error: {str(e)}")
60
+
61
+ @app.post("/stream")
62
+ async def stream(req: StreamRequest):
63
+ """Streaming endpoint for real-time responses"""
64
  headers = {
65
  "Content-Type": "application/json",
66
  "Authorization": f"Bearer {DEEPSEEK_API_KEY}"
 
68
 
69
  payload = {
70
  "model": "deepseek-chat",
71
+ "messages": [msg.dict() for msg in req.messages],
72
+ "temperature": 0.2,
73
+ "stream": True
74
  }
75
 
76
+ async def generate():
77
+ try:
78
+ # Make streaming request to DeepSeek API
79
+ response = requests.post(
80
+ DEEPSEEK_STREAM_URL,
81
+ headers=headers,
82
+ json=payload,
83
+ stream=True,
84
+ timeout=60
85
+ )
86
+
87
+ response.raise_for_status()
88
+
89
+ # Stream the response from DeepSeek to the client
90
+ for line in response.iter_lines():
91
+ if line:
92
+ decoded_line = line.decode('utf-8').strip()
93
+ if decoded_line.startswith('data: '):
94
+ data = decoded_line[6:] # Remove "data: " prefix
95
+
96
+ if data == '[DONE]':
97
+ yield f"data: {json.dumps({'choices': [{'delta': {'content': ''}}]})}\n\n"
98
+ yield "data: [DONE]\n\n"
99
+ break
100
+
101
+ try:
102
+ parsed_data = json.loads(data)
103
+
104
+ # Extract content from DeepSeek response
105
+ if 'choices' in parsed_data and len(parsed_data['choices']) > 0:
106
+ choice = parsed_data['choices'][0]
107
+ if 'delta' in choice and 'content' in choice['delta']:
108
+ content = choice['delta']['content']
109
+ if content:
110
+ # Forward the SSE event to client
111
+ yield f"data: {json.dumps({'choices': [{'delta': {'content': content}}]})}\n\n"
112
+
113
+ except json.JSONDecodeError:
114
+ continue
115
+
116
+ except requests.exceptions.RequestException as e:
117
+ error_message = f"DeepSeek API streaming error: {str(e)}"
118
+ yield f"data: {json.dumps({'error': error_message})}\n\n"
119
+ yield "data: [DONE]\n\n"
120
+ except Exception as e:
121
+ error_message = f"Unexpected error: {str(e)}"
122
+ yield f"data: {json.dumps({'error': error_message})}\n\n"
123
+ yield "data: [DONE]\n\n"
124
 
125
+ return StreamingResponse(
126
+ generate(),
127
+ media_type="text/event-stream",
128
+ headers={
129
+ "Cache-Control": "no-cache",
130
+ "Connection": "keep-alive",
131
+ "X-Accel-Buffering": "no" # Disable buffering for nginx
132
+ }
133
+ )
134
 
135
+ @app.get("/test-stream")
136
+ async def test_stream():
137
+ """Test endpoint to verify streaming is working"""
138
+ async def generate_test():
139
+ test_messages = [
140
+ "Hello! ",
141
+ "I'm your AI teacher. ",
142
+ "How can I help you today? ",
143
+ "I can explain mathematics, ",
144
+ "science, and other subjects. ",
145
+ "What would you like to learn?",
146
+ ]
147
+
148
+ for msg in test_messages:
149
+ yield f"data: {json.dumps({'choices': [{'delta': {'content': msg}}]})}\n\n"
150
+ await asyncio.sleep(0.5)
151
+
152
+ yield "data: [DONE]\n\n"
153
+
154
+ return StreamingResponse(
155
+ generate_test(),
156
+ media_type="text/event-stream"
157
+ )