File size: 2,606 Bytes
9fc4d76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import os
from openai import OpenAI
from rag_module.vector_store import query_store
from utils.incident_logger import load_incidents

HF_MODEL = "meta-llama/Llama-3.1-8B-Instruct"


def _get_client():
    token = os.getenv("HF_TOKEN")
    if not token:
        raise EnvironmentError(
            "HF_TOKEN not set.\n"
            "Get your free token at: https://huggingface.co/settings/tokens\n"
            "Then in PowerShell: $env:HF_TOKEN='hf_xxxxxxxxxxxxxxxx'"
        )
    return OpenAI(
        base_url="https://router.huggingface.co/v1",
        api_key=token,
    )


def _build_prompt(context_docs: list[dict], user_query: str) -> str:
    context_lines = "\n".join(
        f"- [{d.get('timestamp', '?')}] Plate: {d.get('plate', '?')} | "
        f"Type: {d.get('vehicle_class', '?')} | Zone: {d.get('zone', '?')} | "
        f"Status: {d.get('status', '?')} | Notes: {d.get('notes', '') or 'none'}"
        for d in context_docs
    )
    return (
        f"You are a smart parking security assistant. "
        f"You MUST answer based on the incident log below. "
        f"Even if there is only one record, use it to answer. "
        f"Never say there is no data if records are shown below.\n\n"
        f"--- INCIDENT LOG ---\n{context_lines}\n--------------------\n\n"
        f"Question: {user_query}\n\n"
        f"Answer directly and factually using the records above:"
    )


def ask(user_query: str, n_context: int = 5) -> dict:
    retrieved = query_store(user_query, n_results=n_context)

    # Fallback: load directly from CSV if vector store is empty
    if not retrieved:
        df = load_incidents()
        if not df.empty:
            retrieved = df.head(20).to_dict(orient="records")
            for r in retrieved:
                if hasattr(r.get("timestamp"), "strftime"):
                    r["timestamp"] = r["timestamp"].strftime("%Y-%m-%d %H:%M:%S")

    if not retrieved:
        return {
            "answer": "No incident records found. Run detection or seed sample data first.",
            "retrieved_docs": [],
        }

    prompt = _build_prompt(retrieved, user_query)

    try:
        client = _get_client()
        response = client.chat.completions.create(
            model=HF_MODEL,
            messages=[{"role": "user", "content": prompt}],
            max_tokens=400,
            temperature=0.2,
        )
        answer = response.choices[0].message.content.strip()
    except EnvironmentError as e:
        answer = str(e)
    except Exception as e:
        answer = f"Error: {e}"

    return {"answer": answer, "retrieved_docs": retrieved}