Skip to content

Commit b32a008

Browse files
author
RobuRishabh
committed
Containerization_done
1 parent 526b3b4 commit b32a008

File tree

3 files changed

+164
-114
lines changed

3 files changed

+164
-114
lines changed

mock_database.py

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,38 @@ def check_ollama_availability():
2626
{"flight_number": "MI500", "origin": "Miami", "destination": "Rio de Janeiro", "time": "2025-05-02 07:30", "airline": "South American Airways"}
2727
]
2828

29-
def search_flights(query):
30-
"""Search for flights based on keywords in the query."""
31-
query_lower = query.lower()
32-
33-
# Match flights by checking if the query is present in any flight attribute
29+
def search_flights(origin=None, destination=None, flight_number=None, airline=None):
30+
"""
31+
Search for flights based on exact matches for origin, destination, flight number, or airline.
32+
Ensures that at least one valid filter is applied.
33+
"""
34+
print(f"🔍 Searching for: Origin={origin}, Destination={destination}, Flight Number={flight_number}, Airline={airline}")
35+
36+
# ✅ If flight number is provided, prioritize searching by flight number only
37+
if flight_number:
38+
matches = [flight for flight in flights if flight["flight_number"].lower() == flight_number.lower()]
39+
print(f"🔎 Flight number search results: {matches}")
40+
return matches
41+
42+
# ✅ If no flight number, apply standard search
43+
if not any([origin, destination, airline]):
44+
print("⚠️ No valid search parameters provided. Returning an empty list.")
45+
return []
46+
47+
# Normalize input (convert to lowercase)
48+
origin = origin.lower() if origin else None
49+
destination = destination.lower() if destination and destination != "city name" else None # Ignore "City Name"
50+
airline = airline.lower() if airline else None
51+
52+
# Filter flights with exact matching for provided fields
3453
matches = [
35-
flight for flight in flights
36-
if query_lower in flight["origin"].lower()
37-
or query_lower in flight["destination"].lower()
38-
or query_lower in flight["flight_number"].lower()
39-
or query_lower in flight["airline"].lower()
54+
flight for flight in flights
55+
if (not origin or flight["origin"].lower() == origin)
56+
and (not destination or flight["destination"].lower() == destination)
57+
and (not airline or flight["airline"].lower() == airline)
4058
]
41-
59+
60+
print(f"🔎 Found flights: {matches}")
4261
return matches
4362

4463
if __name__ == "__main__":

ollama_api.py

Lines changed: 18 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,15 @@
11
import os
22
import json
33
import requests
4-
from langchain_ollama import OllamaLLM
4+
from langchain_ollama import OllamaLLM # Correct import
55
from typing import Tuple, List
66
from dotenv import load_dotenv
77

8-
# Load environment variables
98
load_dotenv()
10-
11-
# Set default Ollama settings
129
OLLAMA_URL = os.getenv("OLLAMA_URL", "http://localhost:11434")
13-
OLLAMA_MODEL = os.getenv("OLLAMA_MODEL", "llama2:latest") # Use default if not set
14-
15-
if not OLLAMA_MODEL:
16-
print("❌ OLLAMA_MODEL is missing! Using default model: 'llama2:latest'.")
10+
OLLAMA_MODEL = os.getenv("OLLAMA_MODEL", "llama2:latest")
1711

18-
# Initialize Ollama LLM
1912
def initialize_ollama():
20-
"""Initialize the Ollama LLM model safely."""
2113
try:
2214
ollama_llm = OllamaLLM(model=OLLAMA_MODEL, base_url=OLLAMA_URL)
2315
print(f"🟢 Successfully initialized Ollama LLM with model: {OLLAMA_MODEL}")
@@ -29,75 +21,43 @@ def initialize_ollama():
2921
ollama_llm = initialize_ollama()
3022

3123
def check_ollama_availability() -> Tuple[bool, str]:
32-
"""Check if the locally running Ollama server is available."""
3324
try:
3425
response = requests.get(f"{OLLAMA_URL}/api/tags", timeout=3)
35-
if response.status_code == 200:
36-
return True, "🟢 Ollama server is available"
37-
return False, f"❌ Ollama server returned status code: {response.status_code}"
38-
except requests.exceptions.Timeout:
39-
return False, "⚠️ Ollama server timeout. It may be overloaded or down."
40-
except requests.exceptions.ConnectionError:
41-
return False, "❌ Cannot connect to Ollama server. Ensure it is running."
42-
except Exception as e:
43-
return False, f"⚠️ Error checking Ollama server: {str(e)}"
26+
return response.status_code == 200, f"🟢 Ollama server is available at {OLLAMA_URL}"
27+
except requests.RequestException as e:
28+
return False, f"⚠️ Ollama server is not available at {OLLAMA_URL}: {str(e)}"
4429

4530
def generate_fallback_response(query: str, flights: List[dict]) -> str:
46-
"""Generate a simple response when Ollama is not available."""
4731
if not flights:
48-
return "I couldn't find any flights matching your criteria. Please try again with different details."
49-
32+
return "I couldn't find any flights matching your criteria. Please try again."
5033
response = "Here are the flights that match your search:\n\n"
5134
for flight in flights:
5235
response += (
53-
"✈️ Flight {flight_number} from {origin} to {destination}\n"
54-
"⏰ Time: {time}\n"
55-
"🏢 Airline: {airline}\n\n"
56-
).format(
57-
flight_number=flight.get("flight_number", "Unknown"),
58-
origin=flight.get("origin", "Unknown"),
59-
destination=flight.get("destination", "Unknown"),
60-
time=flight.get("time", "N/A"),
61-
airline=flight.get("airline", "N/A")
36+
f"✈️ Flight {flight.get('flight_number', 'Unknown')} from {flight.get('origin', 'Unknown')} to {flight.get('destination', 'Unknown')}\n"
37+
f"⏰ Time: {flight.get('time', 'N/A')}\n"
38+
f"🏢 Airline: {flight.get('airline', 'N/A')}\n\n"
6239
)
6340
return response.strip()
6441

6542
def generate_response(query: str, flights: List[dict]) -> str:
66-
"""Generate a natural language response using the LangChain Ollama integration."""
6743
is_available, message = check_ollama_availability()
68-
if not is_available:
69-
print(f"⚠️ {message}")
70-
return generate_fallback_response(query, flights)
71-
72-
if not ollama_llm:
73-
print("⚠️ Ollama model is not initialized. Using fallback response.")
44+
if not is_available or not ollama_llm:
45+
print(f"⚠️ {message if not is_available else 'Ollama model not initialized'}")
7446
return generate_fallback_response(query, flights)
7547

7648
try:
77-
if flights:
78-
flight_info = json.dumps(flights, indent=2)
79-
prompt = f"""
80-
User Query: {query}
81-
82-
Available Flights:
83-
{flight_info}
84-
85-
Generate a natural language response summarizing these flights, including flight number, time, and airline details.
86-
"""
87-
else:
88-
prompt = f"""
89-
User Query: {query}
90-
91-
No matching flights found. Please provide a response indicating this politely.
92-
"""
93-
49+
flight_info = json.dumps(flights, indent=2) if flights else "No matching flights found."
50+
prompt = f"""
51+
User Query: {query}
52+
Available Flights: {flight_info}
53+
Generate a natural language response summarizing these flights, including flight number, time, and airline details if available, or politely indicate no flights were found.
54+
"""
9455
print("🟢 Sending prompt to Ollama for response generation...")
9556
response = ollama_llm.invoke(prompt)
9657
return response.strip() if response else generate_fallback_response(query, flights)
97-
9858
except Exception as e:
9959
print(f"⚠️ Ollama LLM generation failed: {str(e)}")
100-
return generate_fallback_response(query, flights) + f" (⚠️ Error: {str(e)})"
60+
return generate_fallback_response(query, flights)
10161

10262
# Test
10363
if __name__ == "__main__":

query_handler.py

Lines changed: 116 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,159 @@
1-
import ollama
21
import json
32
import os
43
import re
54
from dotenv import load_dotenv
5+
from langchain_ollama import OllamaLLM
66
from mock_database import search_flights, check_ollama_availability
77

88
# Load environment variables
99
load_dotenv()
10-
OLLAMA_MODEL = os.getenv("OLLAMA_MODEL", "llama2:latest") # Load model dynamically
11-
10+
OLLAMA_MODEL = os.getenv("OLLAMA_MODEL", "llama2:latest")
1211
OLLAMA_AVAILABLE = check_ollama_availability()
1312

14-
def extract_entities_llama2(query):
13+
# Initialize Ollama LLM
14+
def initialize_ollama():
15+
"""Initialize the Ollama LLM model safely."""
16+
try:
17+
ollama_llm = OllamaLLM(model=OLLAMA_MODEL)
18+
print(f"🟢 Successfully initialized Ollama LLM with model: {OLLAMA_MODEL}")
19+
return ollama_llm
20+
except Exception as e:
21+
print(f"❌ Failed to initialize Ollama LLM: {str(e)}")
22+
return None
23+
24+
ollama_llm = initialize_ollama()
25+
26+
CITY_MAPPING = {
27+
"ny": "New York",
28+
"la": "Los Angeles",
29+
"ch": "Chicago",
30+
"sf": "San Francisco",
31+
"mi": "Miami"
32+
}
33+
34+
def extract_entities_ollama(query):
1535
"""
16-
Uses Ollama to extract structured flight details from a query.
17-
Ensures the response is always valid JSON.
36+
Uses Ollama to extract structured flight details from a query and ensures correct data mapping.
37+
If Ollama fails to extract an entity, fallback to a keyword-based search.
1838
"""
19-
if not OLLAMA_AVAILABLE:
39+
if not OLLAMA_AVAILABLE or not ollama_llm:
2040
print("⚠️ Ollama server is unavailable. Using basic keyword search.")
2141
return {}
2242

2343
print(f"🟢 Using Ollama model: {OLLAMA_MODEL}")
24-
prompt = f'''
25-
Extract flight details from this user query and respond **only** in valid JSON.
26-
Do not include any extra text, explanations, or markdown.
27-
44+
prompt = f"""
45+
Extract flight details from the following user query and return only valid JSON.
46+
Do not include any explanations, additional text, or markdown.
47+
2848
Query: "{query}"
29-
30-
Example valid responses:
31-
{{"origin": "New York", "destination": "London", "flight_number": "AA123", "time": "10:00 AM", "date": "2025-05-01", "airline": "Global Airways"}}
32-
{{"origin": "Chicago", "destination": null, "flight_number": null, "time": null, "date": null, "airline": null}}
49+
50+
The response should be in this exact JSON format:
51+
{{
52+
"origin": "City Name",
53+
"destination": "City Name",
54+
"flight_number": "Flight Number",
55+
"date": "YYYY-MM-DD",
56+
"airline": "Airline Name"
57+
}}
3358
3459
If a value is missing, set it to `null`.
35-
36-
'''
60+
"""
3761

3862
try:
39-
print(f"🟢 Sending request to Ollama with model: {OLLAMA_MODEL}")
40-
response = ollama.chat(model=OLLAMA_MODEL.strip(), messages=[{"role": "user", "content": prompt}])
41-
content = response["message"]["content"].strip()
63+
print(f"🟢 Sending request to Ollama for entity extraction...")
64+
response = ollama_llm.invoke(prompt)
4265

43-
# 🔍 Extract the valid JSON from the response
44-
json_match = re.search(r"\{.*\}", content, re.DOTALL)
66+
# Extract valid JSON from response
67+
json_match = re.search(r"\{.*\}", response, re.DOTALL)
4568
if json_match:
46-
json_str = json_match.group(0) # Extract JSON part
47-
extracted = json.loads(json_str) # Convert to dictionary
69+
json_str = json_match.group(0)
70+
extracted = json.loads(json_str)
4871

49-
# 🛠️ Clean extracted data (remove placeholders)
50-
extracted_clean = {k: v for k, v in extracted.items() if v and v.lower() not in ["null", "none"]}
72+
# ✅ Clean extracted values
73+
if extracted.get("destination") == "City Name":
74+
extracted["destination"] = None # Ignore placeholder values
75+
if extracted.get("origin") == "NYC":
76+
extracted["origin"] = "New York" # Fix Ollama misinterpretation
5177

52-
print(f"🟢 Extracted Entities: {extracted_clean}")
78+
# ✅ If no flight number is extracted, try regex
79+
if not extracted.get("flight_number"):
80+
extracted["flight_number"] = extract_flight_number(query)
81+
82+
extracted_clean = {k: v for k, v in extracted.items() if v} # Remove None values
83+
print(f"🟢 Extracted Entities from Ollama: {extracted_clean}")
5384
return extracted_clean
5485

5586
else:
56-
print(f"⚠️ No valid JSON found in response. Raw response: {content}")
57-
return {}
87+
print(f"⚠️ No valid JSON found in response. Falling back to keyword search.")
88+
return extract_entities_from_keywords(query)
5889

5990
except json.JSONDecodeError as jde:
60-
print(f"⚠️ JSONDecodeError: {jde}. Raw response: {content}")
61-
return {}
91+
print(f"⚠️ JSONDecodeError: {jde}. Falling back to keyword search.")
92+
return extract_entities_from_keywords(query)
6293
except Exception as e:
63-
print(f"⚠️ Error during entity extraction: {e}")
64-
return {}
94+
print(f"⚠️ Error during entity extraction: {e}. Falling back to keyword search.")
95+
return extract_entities_from_keywords(query)
96+
97+
def extract_flight_number(query):
98+
"""
99+
Extracts a flight number from a query using regex.
100+
Flight numbers typically have a two-letter airline code followed by 3-4 digits (e.g., "NY100").
101+
"""
102+
match = re.search(r"\b[A-Z]{2}\d{3,4}\b", query)
103+
return match.group(0) if match else None
104+
105+
106+
def extract_entities_from_keywords(query):
107+
"""
108+
Fallback function to extract entities from a query using simple keyword matching.
109+
"""
110+
keywords = query.lower()
111+
112+
cities = ["new york", "los angeles", "chicago", "san francisco", "miami", "paris", "tokyo", "london", "rio de janeiro", "sydney"]
113+
airlines = ["global airways", "pacific routes", "euro connect", "ocean pacific", "south american airways"]
114+
115+
origin = next((city for city in cities if city in keywords), None)
116+
destination = None # Can't always determine destination reliably from keywords
117+
flight_number_match = re.search(r"\b[A-Z]{2}\d{3,4}\b", query) # Match flight numbers like "NY100"
118+
flight_number = flight_number_match.group(0) if flight_number_match else None
119+
airline = next((air for air in airlines if air in keywords), None)
120+
121+
extracted = {
122+
"origin": origin,
123+
"destination": destination,
124+
"flight_number": flight_number,
125+
"airline": airline
126+
}
127+
128+
extracted_clean = {k: v for k, v in extracted.items() if v} # Remove None values
129+
print(f"🟢 Extracted Entities from Keywords: {extracted_clean}")
130+
return extracted_clean
65131

66132

67133
def process_query(query):
68134
"""
69135
Process user query and return relevant flight information.
70-
Uses keyword search if Ollama is unavailable.
136+
Uses Ollama for entity extraction instead of Transformers.
71137
"""
72138
try:
73139
print(f"🟢 Processing query: {query}")
74140

75-
# Extract structured entities (if Ollama is available)
76-
search_params = extract_entities_llama2(query) if OLLAMA_AVAILABLE else {}
141+
# Extract structured entities using Ollama
142+
search_params = extract_entities_ollama(query)
77143

78-
# Perform a keyword-based search instead of semantic search
79-
if search_params:
80-
print(f"🟢 Searching with extracted parameters: {search_params}")
81-
matching_flights = search_flights(search_params.get("origin", "") or search_params.get("destination", ""))
82-
else:
83-
print("⚠️ No structured entities found. Performing direct keyword search.")
84-
matching_flights = search_flights(query)
144+
# Ensure extracted values are correct before searching
145+
origin = search_params.get("origin")
146+
destination = search_params.get("destination")
147+
flight_number = search_params.get("flight_number")
148+
airline = search_params.get("airline")
149+
150+
print(f"🟢 Searching with extracted parameters: {search_params}")
151+
152+
# Use extracted details for searching
153+
matching_flights = search_flights(origin, destination, flight_number, airline)
85154

86155
if not matching_flights:
87-
return False, "No flights found matching your criteria.", []
156+
return False, "⚠️ No flights found matching your criteria. Please try again with different details.", []
88157

89158
return True, "Here are the flights that match your criteria:", matching_flights
90159

@@ -95,7 +164,9 @@ def process_query(query):
95164
print(f"❌ Unexpected error in process_query: {str(e)}")
96165
return False, f"An error occurred while processing your query: {str(e)}", []
97166

167+
168+
98169
# Test
99170
if __name__ == "__main__":
100-
success, message, flights = process_query("Show me flight NY100")
171+
success, message, flights = process_query("Show me flights from New York to London on May 1st")
101172
print(f"Success: {success}, Message: {message}, Flights: {flights}")

0 commit comments

Comments
 (0)