File size: 2,727 Bytes
b5961aa
 
 
 
 
 
 
 
 
 
 
29b313e
 
 
 
 
 
b5961aa
 
 
 
 
 
445252b
b5961aa
445252b
b5961aa
445252b
b5961aa
 
 
 
445252b
b5961aa
 
 
 
 
 
445252b
b5961aa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29b313e
b5961aa
 
 
 
 
 
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
from chatbot.agents.states.state import SwapState
from chatbot.agents.tools.food_retriever import food_retriever
from chatbot.agents.nodes.app_functions.generate_candidates import generate_numerical_constraints
import logging

# --- Cấu hình logging ---
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

def find_replacement_candidates(state: SwapState):
    logger.info("---NODE: FIND REPLACEMENTS (SELF QUERY)---")
    food_old = state.get("food_old")
    profile = state.get("user_profile", {})
    
    if not food_old:
        logger.warning("⚠️ Không tìm thấy thông tin món cũ (food_old).")
        return {"candidates": []}

    diet_mode = profile.get('diet', '')       # VD: Chế độ HighProtein
    restrictions = profile.get('limitFood', '') # VD: Dị ứng sữa, Thuần chay
    health_status = profile.get('healthStatus', '') # VD: Suy thận

    constraint_prompt = ""
    if restrictions not in ["Không có"]:
        constraint_prompt += f"Yêu cầu bắt buộc: {restrictions}. "
    if health_status not in ["Khỏe mạnh", "Không có", "Bình thường", None]:
        constraint_prompt += f"Phù hợp người bệnh: {health_status}. "
    if diet_mode not in ["Bình thường"]:
        constraint_prompt += f"Chế độ: {diet_mode}."

    # 1. Trích xuất ngữ cảnh từ món cũ
    role = food_old.get("role", "main")       # VD: main, side, carb
    vibe = food_old.get("retrieval_vibe", "Món ăn kèm cơ bản")          # VD: món nhẹ nhàng, món giàu đạm
    meal_type = food_old.get("assigned_meal", "trưa") # VD: trưa
    old_name = food_old.get("name", "")
    numerical_query = generate_numerical_constraints(profile, meal_type)

    # 2. Xây dựng Query tự nhiên để SelfQueryRetriever hiểu
    query = (
        f"Tìm các món ăn đóng vai trò '{role}' phù hợp cho bữa '{meal_type}'. Phong cách: '{vibe}'. "
        f"Khác với món '{old_name}'. "
        f"{constraint_prompt}"
    )

    if numerical_query:
        query += f"Yêu cầu: {numerical_query}"
    logger.info(f"🔎 Query: {query}")

    # 3. Gọi Retriever
    try:
        docs = food_retriever.invoke(query)
    except Exception as e:
        logger.info(f"⚠️ Lỗi Retriever: {e}")
        return {"candidates": []}

    # 4. Lọc sơ bộ (Python Filter)
    candidates = []
    for doc in docs:
        item = doc.metadata.copy()
        if item.get("name") == old_name: continue
        
        item["target_role"] = role
        item["target_meal"] = meal_type
        candidates.append(item)

    logger.info(f"📚 Tìm thấy {len(candidates)} ứng viên tiềm năng.")
    return {"candidates": candidates}