Aus_F / app.py
minhvtt's picture
Update app.py
47be81f verified
"""
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 bộ máy chuẩn hoá nội dung mô tả bất động sản cho CMS.
INPUT:
- Một chuỗi text thô (plain text)
- Không có HTML
- Có thể dính liền câu, thiếu xuống dòng, thiếu dấu câu chuẩn
NHIỆM VỤ DUY NHẤT:
- Tách nội dung thành các dòng ngắn, dễ đọc
- Mỗi dòng là một ý/câu độc lập
QUY TẮC BẮT BUỘC:
1. TUYỆT ĐỐI KHÔNG:
- Không thêm, bịa, suy đoán, diễn giải hay làm rõ nội dung
- Không sửa nghĩa, không viết lại câu
- Không thêm từ mới, không thêm tiền tố
- Không phân loại ngữ nghĩa (không suy luận đâu là giá, đâu là vị trí, đâu là liên hệ)
2. CHỈ ĐƯỢC PHÉP:
- Giữ nguyên 100% nội dung text gốc
- Chỉ tách câu dựa trên:
- Dấu . ! ? :
- Hoặc khi phát hiện các cụm bắt đầu rõ ràng như:
"Diện tích", "Vị trí", "Giá", "Liên hệ", "Email"
- Giữ nguyên thứ tự xuất hiện
3. OUTPUT FORMAT:
- Trả về JSON duy nhất
- Key: description_lines
- Value: mảng string
- Mỗi phần tử là một dòng text nguyên văn từ input
4. KHÔNG:
- Không HTML
- Không markdown
- Không text giải thích
- Không key nào khác ngoài description_lines
"""
USER_PROMPT_TEMPLATE = """Hãy định dạng mô tả bất động sản sau thành HTML có cấu trúc rõ ràng
theo đúng quy tắc đã nêu:
{description}
LƯU Ý:
- Không thêm nội dung
- Không suy đoán thông tin thiếu
- Chỉ bọc HTML + CSS inline"""
@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
)