Toilatop1sever commited on
Commit
32829b9
·
verified ·
1 Parent(s): 894121c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +132 -0
app.py CHANGED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ from llama_cpp import Llama
6
+ from huggingface_hub import hf_hub_download
7
+ from typing import List, Optional
8
+ import os
9
+ import json
10
+ import uvicorn
11
+
12
+ app = FastAPI()
13
+
14
+ app.add_middleware(
15
+ CORSMiddleware,
16
+ allow_origins=["*"],
17
+ allow_methods=["*"],
18
+ allow_headers=["*"],
19
+ )
20
+
21
+ MODEL_REPO = "bartowski/Qwen2.5-7B-Instruct-GGUF"
22
+ MODEL_FILE = "Qwen2.5-7B-Instruct-Q4_K_M.gguf"
23
+
24
+ llm: Optional[Llama] = None
25
+
26
+ @app.on_event("startup")
27
+ async def startup_event():
28
+ global llm
29
+ if not os.path.exists(MODEL_FILE):
30
+ print(f"Downloading {MODEL_FILE}...")
31
+ hf_hub_download(repo_id=MODEL_REPO, filename=MODEL_FILE, local_dir=".")
32
+ print("Download done!")
33
+ print("Loading model...")
34
+ llm = Llama(
35
+ model_path=MODEL_FILE,
36
+ n_ctx=2048,
37
+ n_threads=2,
38
+ n_gpu_layers=0,
39
+ verbose=False,
40
+ use_mmap=True,
41
+ use_mlock=False,
42
+ )
43
+ print("Model ready!")
44
+
45
+ class Message(BaseModel):
46
+ role: str
47
+ content: str
48
+
49
+ class ChatRequest(BaseModel):
50
+ prompt: str
51
+ history: List[Message] = []
52
+ system_prompt: Optional[str] = "Bạn là một trợ lý AI thông minh, thân thiện. Trả lời ngắn gọn, chính xác, dễ hiểu bằng tiếng Việt. Khi viết code hãy giải thích rõ ràng. Không bịa đặt thông tin."
53
+ max_tokens: int = 1024
54
+ temperature: float = 0.7
55
+ top_p: float = 0.9
56
+
57
+ @app.post("/chat")
58
+ async def chat(req: ChatRequest):
59
+ if llm is None:
60
+ raise HTTPException(status_code=503, detail="Model chưa sẵn sàng, thử lại sau!")
61
+
62
+ if not req.prompt or not req.prompt.strip():
63
+ raise HTTPException(status_code=400, detail="Prompt trống")
64
+
65
+ if len(req.prompt) > 4000:
66
+ raise HTTPException(status_code=400, detail="Prompt quá dài")
67
+
68
+ try:
69
+ messages = [{"role": "system", "content": req.system_prompt}]
70
+
71
+ for msg in req.history[-10:]:
72
+ if msg.role in ("user", "assistant") and msg.content.strip():
73
+ if messages[-1]["role"] == msg.role:
74
+ continue
75
+ messages.append({"role": msg.role, "content": msg.content})
76
+
77
+ if len(messages) > 1 and messages[-1]["role"] == "user":
78
+ messages.pop()
79
+
80
+ messages.append({"role": "user", "content": req.prompt.strip()})
81
+
82
+ print(f">> Prompt: {req.prompt[:80]}")
83
+ print(f">> Messages count: {len(messages)}")
84
+
85
+ def generate():
86
+ full_response = ""
87
+ try:
88
+ for chunk in llm.create_chat_completion(
89
+ messages=messages,
90
+ max_tokens=req.max_tokens,
91
+ temperature=req.temperature,
92
+ top_p=req.top_p,
93
+ stream=True,
94
+ ):
95
+ delta = chunk["choices"][0]["delta"].get("content", "")
96
+ if delta:
97
+ full_response += delta
98
+ yield f"data: {json.dumps({'delta': delta})}\n\n"
99
+ except Exception as e:
100
+ print(f">> Stream error: {e}")
101
+ yield f"data: {json.dumps({'delta': f'[Lỗi: {str(e)}]'})}\n\n"
102
+ finally:
103
+ print(f">> Response: {full_response[:80]}")
104
+ yield "data: [DONE]\n\n"
105
+
106
+ return StreamingResponse(
107
+ generate(),
108
+ media_type="text/event-stream",
109
+ headers={
110
+ "Cache-Control": "no-cache",
111
+ "X-Accel-Buffering": "no",
112
+ }
113
+ )
114
+
115
+ except Exception as e:
116
+ print(f">> Error: {e}")
117
+ raise HTTPException(status_code=500, detail=str(e))
118
+
119
+ @app.get("/")
120
+ async def root():
121
+ return {
122
+ "status": "ok" if llm else "loading",
123
+ "message": "Model ready!" if llm else "Model đang tải...",
124
+ "model": MODEL_FILE
125
+ }
126
+
127
+ @app.get("/health")
128
+ async def health():
129
+ return {"status": "healthy", "model_loaded": llm is not None}
130
+
131
+ if __name__ == "__main__":
132
+ uvicorn.run(app, host="0.0.0.0", port=7860)