""" Real Estate Description Formatter API Uses lightweight AI models from HuggingFace to format real estate descriptions """ from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel from typing import Optional import os from huggingface_hub import InferenceClient # FastAPI app app = FastAPI( title="Real Estate Description Formatter", description="API to format real estate descriptions with AI", version="1.0.0" ) # CORS app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Initialize HuggingFace Inference Client # Sử dụng model mạnh: Qwen2.5-7B-Instruct (7B params, hỗ trợ tiếng Việt) # Alternatives: mistralai/Mistral-7B-Instruct-v0.3, google/gemma-2-7b-it MODEL_NAME = os.getenv("MODEL_NAME", "Qwen/Qwen2.5-7B-Instruct") HF_TOKEN = os.getenv("HF_TOKEN", None) # Optional: for private models or faster inference client = InferenceClient(model=MODEL_NAME, token=HF_TOKEN) # Request/Response Models class RealEstateInput(BaseModel): description: str class RealEstateOutput(BaseModel): original: str formatted_html: str success: bool error: Optional[str] = None # Prompt phức tạp để xử lý form description bất động sản SYSTEM_PROMPT = """Bạn là một chuyên gia định dạng nội dung bất động sản chuyên nghiệp. NHIỆM VỤ: Chuyển đổi mô tả bất động sản "xấu" (không có cấu trúc, viết tắt, thiếu dấu câu) thành HTML được format đẹp mắt với CSS inline. QUY TẮC QUAN TRỌNG: 1. KHÔNG ĐƯỢC thay đổi nội dung text gốc - CHỈ thêm HTML tags và CSS styling 2. PHẢI giữ nguyên tất cả thông tin: giá, diện tích, số phòng, địa chỉ, số điện thoại 3. PHẢI phân tích và nhận diện các thành phần: - Tiêu đề (tên BDS, loại nhà) - Thông tin kỹ thuật (diện tích, hướng, pháp lý) - Mô tả chi tiết (kết cấu, nội thất) - Vị trí (địa chỉ, khu vực, tiện ích xung quanh) - Giá bán - Liên hệ (SĐT, tên người bán) - ... các thành phần khác 4. SỬ DỤNG CẤU TRÚC HTML: -
cho toàn bộ nội dung -

cho tiêu đề chính -
cho thông số kỹ thuật (badge style) -
cho mô tả chi tiết -
cho thông tin vị trí -
cho giá (highlight, font lớn) -
cho thông tin liên hệ 5. CSS INLINE STYLING - Màu sắc hiện đại, dễ đọc: - Property card: background, border radius, shadow - Title: màu đậm, font-size lớn, text-transform uppercase - Specs: badge style với background color khác nhau - Price: màu phù hợp, không quá chói mắt, cũng không quá trầm, nổi bật, font-weight bold, font-size lớn - Icons: không sử dụng icon gì khác. 6. XỬ LÝ VIẾT TẮT: - Giữ nguyên viết tắt nhưng thêm tooltip/title - Ví dụ: Pn, wc OUTPUT FORMAT: Chỉ trả về HTML thuần, KHÔNG kèm markdown hoặc giải thích. """ USER_PROMPT_TEMPLATE = """Hãy format mô tả bất động sản sau thành HTML đẹp với CSS inline: {description} Nhớ: GIỮ NGUYÊN nội dung text, CHỈ thêm HTML/CSS để trình bày đẹp hơn.""" @app.get("/") async def root(): """API root""" return { "name": "Real Estate Description Formatter", "version": "1.0.0", "model": MODEL_NAME, "endpoint": "/format" } @app.post("/format", response_model=RealEstateOutput) async def format_description(input_data: RealEstateInput): """ Format real estate description with AI Example input: { "description": "NHÀ 2 TẦNG HẺM OTO LIÊN HOA VĨNH NGỌC - TÂY NHA TRANG- Diện tích 92m² full ONT- Hướng Đông Bắc- Pháp lý sổ hồng hoàn công..." } """ try: # Prepare messages for chat model messages = [ { "role": "system", "content": SYSTEM_PROMPT }, { "role": "user", "content": USER_PROMPT_TEMPLATE.format(description=input_data.description) } ] # Call HuggingFace Inference API response = client.chat_completion( messages=messages, max_tokens=2000, temperature=0.3, # Low temperature for consistent formatting ) # Extract formatted HTML formatted_html = response.choices[0].message.content.strip() # Clean up markdown if model added it if formatted_html.startswith("```html"): formatted_html = formatted_html.replace("```html", "").replace("```", "").strip() return RealEstateOutput( original=input_data.description, formatted_html=formatted_html, success=True ) except Exception as e: return RealEstateOutput( original=input_data.description, formatted_html="", success=False, error=str(e) ) @app.get("/health") async def health_check(): """Health check endpoint""" return { "status": "healthy", "model": MODEL_NAME, "service": "Real Estate Formatter" } if __name__ == "__main__": import uvicorn uvicorn.run( "app:app", host="0.0.0.0", port=7860, reload=False )