EnzGamers commited on
Commit
c016b94
·
verified ·
1 Parent(s): e879476

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -58
app.py CHANGED
@@ -7,6 +7,33 @@ 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"
@@ -14,18 +41,17 @@ DEVICE = "cpu"
14
 
15
  # --- Chargement du modèle ---
16
  print(f"Début du chargement du modèle : {MODEL_ID}")
17
- model = AutoModelForCausalLM.from_pretrained(
18
- MODEL_ID,
19
- torch_dtype=torch.bfloat16,
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,9 +64,7 @@ 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
@@ -51,18 +75,12 @@ 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):
@@ -72,64 +90,46 @@ async def create_chat_completion(request: ChatCompletionRequest):
72
  elif isinstance(last_message.content, str):
73
  user_prompt = last_message.content
74
 
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
+ # --- LE CONTEXTE D'INGÉNIERIE EST ICI ---
13
+ SYSTEM_PROMPT = """
14
+ Tu es un développeur expert WordPress et WooCommerce senior. Ton objectif est de fournir du code propre, sécurisé, performant et qui respecte les standards de WordPress.
15
+
16
+ ### RÈGLES FONDAMENTALES ###
17
+ 1. Ne jamais modifier les fichiers du cœur (Core Files) : Propose toujours des solutions via un thème enfant (child theme), un plugin personnalisé ou des "code snippets".
18
+ 2. Respecter les Hooks : Utilise systématiquement les actions (`add_action`) et les filtres (`add_filter`) de WordPress et WooCommerce. C'est la base de tout.
19
+ 3. Sécurité d'abord :
20
+ - Échapper les sorties (Escaping) : Utilise `esc_html__()`, `esc_attr__()`, `esc_url()` pour toute donnée affichée.
21
+ - Valider et nettoyer les entrées (Sanitizing) : Utilise `sanitize_text_field()`, `wp_kses_post()` pour toute donnée venant de l'utilisateur.
22
+ - Utiliser les Nonces : Ajoute des `nonces` (`wp_create_nonce`, `wp_verify_nonce`) pour sécuriser les formulaires et les actions AJAX.
23
+ 4. Performance : Privilégie les fonctions natives de WordPress (`WP_Query` au lieu de requêtes SQL directes, API des Transients pour la mise en cache).
24
+ 5. Standards de codage : Respecte les standards de codage officiels de WordPress (indentation, nommage des variables et fonctions).
25
+
26
+ ### CONTEXTE WOOFOMMERCE ###
27
+ - Tu connais parfaitement la structure des produits, des commandes et des clients.
28
+ - Tu maîtrises les hooks spécifiques de WooCommerce (ex: `woocommerce_before_add_to_cart_button`, `woocommerce_thankyou`).
29
+ - Tu sais comment surcharger les templates de WooCommerce correctement via un thème enfant.
30
+
31
+ ### FORMAT DE RÉPONSE ###
32
+ Pour chaque demande de code, fournis :
33
+ 1. Une brève explication de la solution.
34
+ 2. Le bloc de code PHP complet et fonctionnel.
35
+ 3. Une instruction claire sur l'endroit où placer ce code (ex: "Ajoutez ce code dans le fichier `functions.php` de votre thème enfant.").
36
+ """
37
 
38
  # --- Configuration ---
39
  MODEL_ID = "deepseek-ai/deepseek-coder-1.3b-instruct"
 
41
 
42
  # --- Chargement du modèle ---
43
  print(f"Début du chargement du modèle : {MODEL_ID}")
44
+ model = AutoModelForCausalLM.from_pretrained(MODEL_ID, torch_dtype=torch.bfloat16, device_map=DEVICE)
45
+ # CORRECTION DU WARNING : On configure le tokenizer correctement
46
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, padding_side='left')
47
+ tokenizer.pad_token = tokenizer.eos_token # Indiquer que le token de padding est le même que celui de fin
48
+
 
49
  print("Modèle et tokenizer chargés avec succès sur le CPU.")
50
 
51
+ # ... (Le reste du code reste identique) ...
52
+
53
  app = FastAPI()
54
 
 
55
  class ContentPart(BaseModel):
56
  type: str
57
  text: str
 
64
  model: Optional[str] = None
65
  messages: List[ChatMessage]
66
  stream: Optional[bool] = False
67
+ class Config: extra = Extra.ignore
 
 
68
 
69
  class ModelData(BaseModel):
70
  id: str
 
75
  object: str = "list"
76
  data: List[ModelData]
77
 
 
 
78
  @app.get("/models", response_model=ModelList)
79
  async def list_models():
 
80
  return ModelList(data=[ModelData(id=MODEL_ID)])
81
 
82
  @app.post("/chat/completions")
83
  async def create_chat_completion(request: ChatCompletionRequest):
 
 
 
84
  user_prompt = ""
85
  last_message = request.messages[-1]
86
  if isinstance(last_message.content, list):
 
90
  elif isinstance(last_message.content, str):
91
  user_prompt = last_message.content
92
 
93
+ if not user_prompt: return {"error": "Prompt non trouvé."}
 
94
 
95
+ # INJECTION DU SYSTEM PROMPT
96
+ messages_for_model = [
97
+ {'role': 'system', 'content': SYSTEM_PROMPT},
98
+ {'role': 'user', 'content': user_prompt}
99
+ ]
100
+
101
+ # CORRECTION DU WARNING : On passe l'attention_mask
102
  inputs = tokenizer.apply_chat_template(messages_for_model, add_generation_prompt=True, return_tensors="pt").to(DEVICE)
103
 
104
  # Génération de la réponse complète
105
+ outputs = model.generate(
106
+ inputs,
107
+ attention_mask=inputs.attention_mask, # On ajoute l'attention_mask ici
108
+ max_new_tokens=500, # Augmenté pour des réponses plus longues
109
+ do_sample=True,
110
+ temperature=0.1,
111
+ top_k=50,
112
+ top_p=0.95,
113
+ num_return_sequences=1,
114
+ eos_token_id=tokenizer.eos_token_id
115
+ )
116
  response_text = tokenizer.decode(outputs[0][len(inputs[0]):], skip_special_tokens=True)
117
 
 
118
  async def stream_generator():
119
  response_id = f"chatcmpl-{uuid.uuid4()}"
 
 
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.005)
124
+ final_chunk = {"id": response_id, "object": "chat.completion.chunk", "created": int(time.time()), "model": MODEL_ID, "choices": [{"index": 0, "delta": {}, "finish_reason": "stop"}]}
 
 
 
 
 
 
 
 
 
 
 
 
125
  yield f"data: {json.dumps(final_chunk)}\n\n"
 
 
126
  yield "data: [DONE]\n\n"
127
 
 
128
  if request.stream:
129
  return StreamingResponse(stream_generator(), media_type="text/event-stream")
130
  else:
 
131
  return {"choices": [{"message": {"role": "assistant", "content": response_text}}]}
132
 
133
  @app.get("/")
134
  def root():
135
+ return {"status": "Agent spécialisé WordPress/WooCommerce en ligne", "model_id": MODEL_ID}