EnzGamers commited on
Commit
289cf5a
·
verified ·
1 Parent(s): 6f0305f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -45
app.py CHANGED
@@ -7,6 +7,7 @@ import time
7
  import uuid
8
  import json
9
  from typing import Optional, List, Union, Dict, Any
 
10
 
11
  # --- Configuration ---
12
  MODEL_ID = "deepseek-ai/deepseek-coder-1.3b-instruct"
@@ -20,12 +21,16 @@ model = AutoModelForCausalLM.from_pretrained(
20
  device_map=DEVICE
21
  )
22
  tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
 
 
 
 
23
  print("Modèle et tokenizer chargés avec succès sur le CPU.")
24
 
25
  # --- Création de l'application API ---
26
  app = FastAPI()
27
 
28
- # --- Modèles de données pour accepter la structure complexe de l'extension ---
29
  class ContentPart(BaseModel):
30
  type: str
31
  text: str
@@ -38,10 +43,30 @@ class ChatCompletionRequest(BaseModel):
38
  model: Optional[str] = None
39
  messages: List[ChatMessage]
40
  stream: Optional[bool] = False
 
 
 
 
 
 
 
41
 
42
  class Config:
43
  extra = Extra.ignore
44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  class ModelData(BaseModel):
46
  id: str
47
  object: str = "model"
@@ -50,19 +75,15 @@ class ModelData(BaseModel):
50
  class ModelList(BaseModel):
51
  object: str = "list"
52
  data: List[ModelData]
53
-
54
  # --- Définition des API ---
55
 
56
  @app.get("/models", response_model=ModelList)
57
  async def list_models():
58
- """Répond à la requête GET /models pour satisfaire l'extension."""
59
  return ModelList(data=[ModelData(id=MODEL_ID)])
60
 
61
  @app.post("/chat/completions")
62
  async def create_chat_completion(request: ChatCompletionRequest):
63
- """Endpoint principal qui gère la génération de texte en streaming."""
64
-
65
- # On extrait le prompt de l'utilisateur de la structure complexe
66
  user_prompt = ""
67
  last_message = request.messages[-1]
68
  if isinstance(last_message.content, list):
@@ -75,61 +96,41 @@ async def create_chat_completion(request: ChatCompletionRequest):
75
  if not user_prompt:
76
  return {"error": "Prompt non trouvé."}
77
 
78
- # Préparation pour le modèle DeepSeek
79
  messages_for_model = [{'role': 'user', 'content': user_prompt}]
80
- inputs = tokenizer.apply_chat_template(messages_for_model, add_generation_prompt=True, return_tensors="pt").to(DEVICE)
 
 
 
 
 
 
 
 
 
 
 
 
 
81
 
82
- # Génération de la réponse complète
83
- outputs = model.generate(inputs, max_new_tokens=250, do_sample=True, temperature=0.2, top_k=50, top_p=0.95, num_return_sequences=1, eos_token_id=tokenizer.eos_token_id)
84
- response_text = tokenizer.decode(outputs[0][len(inputs[0]):], skip_special_tokens=True)
85
 
86
- # Fonction génératrice pour le streaming
87
  async def stream_generator():
88
  response_id = f"chatcmpl-{uuid.uuid4()}"
89
 
90
- # On envoie la réponse caractère par caractère, au format attendu
91
  for char in response_text:
92
- chunk = {
93
- "id": response_id,
94
- "object": "chat.completion.chunk",
95
- "created": int(time.time()),
96
- "model": MODEL_ID,
97
- "choices": [{
98
- "index": 0,
99
- "delta": {"content": char},
100
- "finish_reason": None
101
- }]
102
- }
103
  yield f"data: {json.dumps(chunk)}\n\n"
104
- await asyncio.sleep(0.01) # Petite pause pour simuler un flux
105
 
106
- # On envoie le chunk final de fin
107
- final_chunk = {
108
- "id": response_id,
109
- "object": "chat.completion.chunk",
110
- "created": int(time.time()),
111
- "model": MODEL_ID,
112
- "choices": [{
113
- "index": 0,
114
- "delta": {},
115
- "finish_reason": "stop"
116
- }]
117
- }
118
  yield f"data: {json.dumps(final_chunk)}\n\n"
119
-
120
- # On envoie le signal [DONE]
121
  yield "data: [DONE]\n\n"
122
 
123
- # Si l'extension demande un stream, on renvoie le générateur
124
  if request.stream:
125
  return StreamingResponse(stream_generator(), media_type="text/event-stream")
126
  else:
127
- # Code de secours si le stream n'est pas demandé (peu probable)
128
  return {"choices": [{"message": {"role": "assistant", "content": response_text}}]}
129
 
130
  @app.get("/")
131
  def root():
132
- return {"status": "API compatible OpenAI en ligne (avec streaming)", "model_id": MODEL_ID}
133
-
134
- # On a besoin de asyncio pour la pause dans le stream
135
- import asyncio
 
7
  import uuid
8
  import json
9
  from typing import Optional, List, Union, Dict, Any
10
+ import asyncio
11
 
12
  # --- Configuration ---
13
  MODEL_ID = "deepseek-ai/deepseek-coder-1.3b-instruct"
 
21
  device_map=DEVICE
22
  )
23
  tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
24
+ if tokenizer.pad_token is None:
25
+ tokenizer.pad_token = tokenizer.eos_token
26
+ print("Le pad_token a été défini sur eos_token.")
27
+
28
  print("Modèle et tokenizer chargés avec succès sur le CPU.")
29
 
30
  # --- Création de l'application API ---
31
  app = FastAPI()
32
 
33
+ # --- Modèles de données ---
34
  class ContentPart(BaseModel):
35
  type: str
36
  text: str
 
43
  model: Optional[str] = None
44
  messages: List[ChatMessage]
45
  stream: Optional[bool] = False
46
+ max_tokens: Optional[int] = 512 # Augmenté pour des réponses plus longues
47
+
48
+ # --- LES NOUVEAUX CHAMPS SONT ICI ---
49
+ # Ajout des paramètres de génération avec des valeurs par défaut.
50
+ temperature: Optional[float] = 0.4
51
+ top_p: Optional[float] = 0.95
52
+ top_k: Optional[int] = 50
53
 
54
  class Config:
55
  extra = Extra.ignore
56
 
57
+ # ... (le reste des modèles de données est inchangé) ...
58
+ class ChatCompletionResponseChoice(BaseModel):
59
+ index: int = 0
60
+ message: ChatMessage
61
+ finish_reason: str = "stop"
62
+
63
+ class ChatCompletionResponse(BaseModel):
64
+ id: str
65
+ object: str = "chat.completion"
66
+ created: int
67
+ model: str
68
+ choices: List[ChatCompletionResponseChoice]
69
+
70
  class ModelData(BaseModel):
71
  id: str
72
  object: str = "model"
 
75
  class ModelList(BaseModel):
76
  object: str = "list"
77
  data: List[ModelData]
78
+
79
  # --- Définition des API ---
80
 
81
  @app.get("/models", response_model=ModelList)
82
  async def list_models():
 
83
  return ModelList(data=[ModelData(id=MODEL_ID)])
84
 
85
  @app.post("/chat/completions")
86
  async def create_chat_completion(request: ChatCompletionRequest):
 
 
 
87
  user_prompt = ""
88
  last_message = request.messages[-1]
89
  if isinstance(last_message.content, list):
 
96
  if not user_prompt:
97
  return {"error": "Prompt non trouvé."}
98
 
 
99
  messages_for_model = [{'role': 'user', 'content': user_prompt}]
100
+ text_prompt = tokenizer.apply_chat_template(messages_for_model, tokenize=False, add_generation_prompt=True)
101
+ inputs = tokenizer(text_prompt, return_tensors="pt", padding=True).to(DEVICE)
102
+
103
+ # --- LA MISE À JOUR EST ICI ---
104
+ # On utilise maintenant les paramètres de la requête pour la génération.
105
+ outputs = model.generate(
106
+ **inputs,
107
+ max_new_tokens=request.max_tokens,
108
+ do_sample=True, # do_sample doit être True pour que temp, top_p et top_k aient un effet
109
+ temperature=request.temperature,
110
+ top_p=request.top_p,
111
+ top_k=request.top_k,
112
+ eos_token_id=tokenizer.eos_token_id
113
+ )
114
 
115
+ response_text = tokenizer.decode(outputs[0, inputs['input_ids'].shape[1]:], skip_special_tokens=True)
 
 
116
 
 
117
  async def stream_generator():
118
  response_id = f"chatcmpl-{uuid.uuid4()}"
119
 
 
120
  for char in response_text:
121
+ chunk = { "id": response_id, "object": "chat.completion.chunk", "created": int(time.time()), "model": MODEL_ID, "choices": [{"index": 0, "delta": {"content": char}, "finish_reason": None }] }
 
 
 
 
 
 
 
 
 
 
122
  yield f"data: {json.dumps(chunk)}\n\n"
123
+ await asyncio.sleep(0.01)
124
 
125
+ final_chunk = { "id": response_id, "object": "chat.completion.chunk", "created": int(time.time()), "model": MODEL_ID, "choices": [{"index": 0, "delta": {}, "finish_reason": "stop" }] }
 
 
 
 
 
 
 
 
 
 
 
126
  yield f"data: {json.dumps(final_chunk)}\n\n"
 
 
127
  yield "data: [DONE]\n\n"
128
 
 
129
  if request.stream:
130
  return StreamingResponse(stream_generator(), media_type="text/event-stream")
131
  else:
 
132
  return {"choices": [{"message": {"role": "assistant", "content": response_text}}]}
133
 
134
  @app.get("/")
135
  def root():
136
+ return {"status": "API compatible OpenAI en ligne (avec streaming et paramètres dynamiques)", "model_id": MODEL_ID}