File size: 3,348 Bytes
e57a398
 
4452393
 
b923c32
 
 
 
4452393
 
 
b923c32
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e57a398
 
b923c32
 
 
4452393
 
 
 
 
 
b923c32
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e57a398
b923c32
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e57a398
 
 
 
 
 
b923c32
e57a398
b923c32
 
 
 
 
4452393
 
 
 
 
 
 
 
b923c32
4452393
 
 
 
 
 
 
 
 
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import spacy
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional, Dict, Any

# Load spaCy language model
nlp = spacy.load("en_core_web_sm")

# FastAPI instance
app = FastAPI()

# Define mappings for categories and filters
KEYWORD_MAPPINGS = {
    "categories": {
        "salon": "Salon",
        "spa": "Spa",
        "gym": "Fitness",
        "fitness": "Fitness",
        "pet spa": "Pet Spa",
        "dental": "Dental",
        "nail art": "Nail Art",
        "tattoo": "Tattoo",
    },
    "filters": {
        "top": {"top_rated": True},
        "top-rated": {"top_rated": True},
        "highly-rated": {"top_rated": True},
        "best": {"top_rated": True},
        "popular": {"popular": True},
        "trending": {"trending": True},
        "near me": {"radius": 500},
        "around me": {"radius": 500},
        "nearby": {"radius": 500},
    },
}

# Pydantic schema for the input query
class QueryRequest(BaseModel):
    sentence: str
    latitude: Optional[float] = None
    longitude: Optional[float] = None

def parse_sentence_to_query_ner(sentence: str, lat: Optional[float] = None, lng: Optional[float] = None) -> Dict[str, Any]:
    """
    Parse a sentence using spaCy NER and build a search query.

    Args:
        sentence (str): Input sentence to parse.
        lat (Optional[float]): Latitude for geolocation.
        lng (Optional[float]): Longitude for geolocation.

    Returns:
        Dict[str, Any]: Parsed search query.
    """
    # Initialize query with defaults
    query = {
        "location_id": None,
        "latitude": lat,
        "longitude": lng,
        "radius": None,
        "merchant_category": None,
        "business_name": None,
        "top_rated": False,
        "popular": False,
        "trending": False,
    }

    # Process the sentence using spaCy
    doc = nlp(sentence)

    # Extract categories from sentence using token matching
    for token in doc:
        for keyword, category in KEYWORD_MAPPINGS["categories"].items():
            if keyword in token.text.lower():
                query["merchant_category"] = category
                break

    # Extract filters using token and phrase matching
    for phrase, filter_dict in KEYWORD_MAPPINGS["filters"].items():
        if phrase in sentence.lower():
            query.update(filter_dict)

    # Extract potential business names using NER
    for ent in doc.ents:
        if ent.label_ in ["ORG", "PERSON", "GPE"]:  # Relevant entity types
            query["business_name"] = ent.text
            break

    # Use NER to extract location context
    if "near me" in sentence.lower() or "around me" in sentence.lower() or "nearby" in sentence.lower():
        if lat is not None and lng is not None:
            query["radius"] = 500  # Default radius for "near me"

    return query

# FastAPI route
@app.post("/parse-query/")
async def parse_query(request: QueryRequest):
    """
    API endpoint to parse a query and return a structured response.

    Args:
        request (QueryRequest): Input sentence and optional location data.

    Returns:
        Dict[str, Any]: Parsed search query.
    """
    parsed_query = parse_sentence_to_query_ner(
        sentence=request.sentence,
        lat=request.latitude,
        lng=request.longitude
    )
    return {"query": parsed_query}