File size: 3,026 Bytes
00d1ce3
6d92e94
 
 
 
00d1ce3
20d628f
 
 
c36ca92
20d628f
6da75e7
d57c514
271494a
 
 
132ffa7
6d92e94
 
d57c514
 
 
 
 
 
 
 
48a6496
 
 
20d628f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
00d1ce3
 
 
 
 
20d628f
 
 
00d1ce3
20d628f
 
 
 
 
48a6496
 
 
 
 
20d628f
48a6496
 
20d628f
 
00d1ce3
 
 
 
 
20d628f
48a6496
00d1ce3
 
48a6496
 
 
 
00d1ce3
 
48a6496
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import os
# Thư mục cache có quyền ghi
os.environ["HF_HOME"] = "/tmp/hf_cache"
os.environ["TRANSFORMERS_CACHE"] = "/tmp/hf_cache"
os.environ["HF_DATASETS_CACHE"] = "/tmp/hf_cache"
import torch
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional
from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM
from fastapi.middleware.cors import CORSMiddleware

# ==== Hugging Face token & model ====
model_name = "lingling707/vit5-skinbot"
hf_token = os.getenv("HF_TOKEN")


tokenizer = AutoTokenizer.from_pretrained(model_name, token=hf_token, local_files_only=False)
model = AutoModelForSeq2SeqLM.from_pretrained(model_name, token=hf_token, local_files_only=False)

# ==== Chatbot pipeline ====
chatbot = pipeline(
    "text2text-generation",
    model=model,
    tokenizer=tokenizer,
    device=0  # GPU: 0, CPU: -1
)

# ==== Model phân loại ảnh da ====
image_model = pipeline("image-classification", model="dima806/skin_types_image_detection")

# ==== FastAPI setup ====
app = FastAPI()
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

class RequestData(BaseModel):
    userMessage: str
    imageUrl: Optional[str] = None

def map_labels_to_skin_type(label: str):
    label = label.lower()
    return {
        "oily": "da dầu, dễ nổi mụn",
        "dry": "da khô, có thể bong tróc hoặc lão hóa sớm",
        "normal": "da thường, cân bằng"
    }.get(label, "không xác định rõ loại da")

@app.get("/")
async def root():
    return {"message": "Skin Advisor API (Vit5 Fine-Tune) is running 🚀"}

@app.post("/skinAdvisor")
async def skin_advisor(data: RequestData):
    skin_analysis = ""

    if data.imageUrl and data.imageUrl.startswith(("http://","https://")):
        try:
            results = image_model(data.imageUrl)
            top = max(results, key=lambda x: x['score'])
            skin_type = map_labels_to_skin_type(top['label'])
            skin_analysis = f"Ảnh phân tích cho thấy: {skin_type}."
        except Exception as e:
            print("Image analysis error:", e)
            skin_analysis = "Không thể phân tích ảnh da."

    prompt = (
        f"Bạn là chuyên gia tư vấn chăm sóc da. {skin_analysis} Người dùng hỏi: {data.userMessage}. "
        "Hãy trả lời ngắn gọn, thân thiện, bằng tiếng Việt, "
        "chỉ tư vấn chăm sóc da, tuyệt đối không gợi ý nguy hiểm."
    )

    try:
        result = chatbot(prompt, max_new_tokens=120, truncation=True)
        reply = result[0]["generated_text"].strip() or "Xin lỗi, mình chưa có câu trả lời phù hợp."
    except Exception as e:
        print("Error:", e)
        reply = "Xin lỗi, bot chưa trả lời được. Vui lòng thử lại."

    if skin_analysis and skin_analysis.lower() not in reply.lower():
        reply = f"{skin_analysis} {reply}"
    return {"reply": reply}