Izazo / src /agent.py
NovakTJ
clean commit vasinih promena
ca5d3ff
# # This file will contain the core logic for the TurBot agent,
# # including the LangGraph setup, state management, and tool definition.
#
# import os
# from typing import List
# from dotenv import load_dotenv
# from huggingface_hub.inference._client import InferenceClient
# from langchain_community.vectorstores import FAISS
# from langchain_huggingface import HuggingFaceEmbeddings
# from langchain_core.messages import HumanMessage, AIMessage
#
# # Load environment variables
# load_dotenv()
#
# # Initialize the LLM (using a free model from Hugging Face)
# client = InferenceClient("meta-llama/Meta-Llama-3-70B-Instruct")
#
# # Load the vector store
# DB_FAISS_PATH = "../vectorstore/db_faiss"
#
# def search_travel_packages(query: str) -> str:
# """
# Search for travel packages based on the user's query.
# This function searches through the travel package documents to find relevant information.
# """
# print(f"BURAAAZ STA SAM JA USAO U SEARCH TRAVEL PACKAGES OVO STVARNO NISAM OCEKIVAO")
# try:
# # Load the vector store
# embeddings = HuggingFaceEmbeddings(
# model_name='sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2',
# model_kwargs={'device': 'cpu'}
# )
#
# if os.path.exists(DB_FAISS_PATH):
# vectorstore = FAISS.load_local(DB_FAISS_PATH, embeddings)
#
#
# print(f"JOOOO USPEJO SAM")
#
# # Search for relevant documents
# docs = vectorstore.similarity_search(query, k=3)
#
# # Combine the relevant information
# context = "\n\n".join([doc.page_content for doc in docs])
# return f"Found relevant travel information:\n\n{context}"
# else:
# return "Travel package database not found. Please ensure the vector store has been created."
# except Exception as e:
# return f"Error searching travel packages: {str(e)}"
#
# def should_search_travel_info(message: str) -> bool:
# print(f"BURAZENGIJA SRA CU JA U SHOULD SEARCH TRAVEL INFU")
# """Decide whether to search for travel information based on the message content."""
# message_lower = message.lower()
#
# # Keywords that indicate we should search for travel information
# travel_keywords = [
# "destinacija", "let", "hotel", "putovanje", "mediteran", "grčka", "italija",
# "turska", "budžet", "porodica", "all inclusive", "preporučite", "ponuda",
# "destination", "flight", "travel", "mediterranean", "greece", "italy",
# "turkey", "budget", "family", "recommend", "offer"
# ]
#
# return any(keyword in message_lower for keyword in travel_keywords)
#
# def chat_with_turbot(message: str, history: List[List[str]]) -> str:
# print(f"BURAZ KOJI JE OVO KITA MOJA")
# """
# Main function to chat with TurBot.
# """
# # Prepare the system message first
# system_message = """Ti si TurBot, digitalni asistent za turističku agenciju.
# Odgovori na srpskom jeziku i budi koristan i prijateljski nastrojen.
# Ako ne znaš odgovor na pitanje, preporuči korisniku da pita o putovanjima, letovima, hotelima ili destinacijama."""
#
# # Convert messages to the format expected by InferenceClient
# messages_for_client = []
#
# # Add system message first (only once)
# messages_for_client.append({"role": "system", "content": system_message})
#
# # Add conversation history
# for human, ai in history:
# if human:
# messages_for_client.append({"role": "user", "content": human})
# if ai:
# messages_for_client.append({"role": "assistant", "content": ai})
#
# # Add the current message
# messages_for_client.append({"role": "user", "content": message})
#
# # Check if we should search for travel information
# context = ""
# if should_search_travel_info(message):
# context = search_travel_packages(message)
# if context:
# # Add context as additional information
# messages_for_client.append({"role": "user", "content": f"Kontekst o putovanjima: {context}"})
#
# try:
# # Debug: Print messages being sent to model
# print(f"\n🔍 DEBUG: Sending {len(messages_for_client)} messages to model:")
# for i, msg in enumerate(messages_for_client):
# print(f" {i+1}. {msg['role']}: {msg['content'][:100]}...")
#
# # Generate response
# response = ""
# for message_chunk in client.chat_completion(
# messages_for_client,
# stream=True,
# max_tokens=512,
# temperature=0.7,
# top_p=0.95,
# ):
# if hasattr(message_chunk, 'choices') and message_chunk.choices:
# token = message_chunk.choices[0].delta.content
# if token:
# response += token
#
# return response if response else "Izvinjavam se, nisam dobio odgovor od modela. Pokušajte ponovo."
# except Exception as e:
# return f"Izvinjavam se, došlo je do greške: {str(e)}"
import os
from typing import List
from dotenv import load_dotenv
from huggingface_hub.inference._client import InferenceClient
from langchain_community.vectorstores import FAISS
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_core.messages import HumanMessage, AIMessage
# Load environment variables
load_dotenv()
# Initialize the LLM (using a free model from Hugging Face)
client = InferenceClient("meta-llama/Meta-Llama-3-70B-Instruct")
# Load the vector store
DB_FAISS_PATH = "../vectorstore/db_faiss"
# --- KLJUČNA IZMENA: Učitaj embeddings model i FAISS bazu SAMO JEDNOM na početku ---
# Inicijalizuj embeddings model globalno (ili bar van funkcije search_travel_packages)
print("Initializing HuggingFaceEmbeddings...")
try:
embeddings_model = HuggingFaceEmbeddings(
model_name='sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2',
model_kwargs={'device': 'cpu'} # Možeš probati 'cuda' ako imaš GPU i PyTorch sa CUDA
)
print("HuggingFaceEmbeddings initialized.")
except Exception as e:
print(f"Error initializing embeddings: {str(e)}")
embeddings_model = None # Postavi na None ako dođe do greške
# Učitaj FAISS vektor bazu globalno
vectorstore = None
if embeddings_model:
print(f"JOOOOO EMBEDINGS POSTOJI BACI MOJ")
if embeddings_model and os.path.exists(DB_FAISS_PATH):
print(f"Loading FAISS vector store from {DB_FAISS_PATH}...")
try:
vectorstore = FAISS.load_local(DB_FAISS_PATH, embeddings_model, allow_dangerous_deserialization=True)
print("FAISS vector store loaded successfully.")
except Exception as e:
print(f"Error loading FAISS vector store: {str(e)}. Make sure 'faiss-cpu' is installed and vectorstore is valid.")
vectorstore = None
else:
print("FAISS vector store path does not exist or embeddings model failed to initialize. RAG will not function.")
# --- KRAJ KLJUČNE IZMENE ---
def search_travel_packages(query: str) -> str:
"""
Search for travel packages based on the user's query.
This function searches through the travel package documents to find relevant information.
"""
print(f"BURAAAZ STA SAM JA USAO U SEARCH TRAVEL PACKAGES OVO STVARNO NISAM OCEKIVAO")
if vectorstore is None:
return "Travel package database is not available. Please ensure the vector store has been created and loaded correctly."
try:
# Nema više učitavanja embeddings i vectorstore OVDE! Koristimo globalne instance.
print(f"JOOOO USPEJO SAM (now searching)...") # Poruka je sada relevantnija
# Search for relevant documents
docs = vectorstore.similarity_search(query, k=3)
# Combine the relevant information
context = "\n\n".join([doc.page_content for doc in docs])
return f"Found relevant travel information:\n\n{context}"
except Exception as e:
return f"Error searching travel packages: {str(e)}"
def should_search_travel_info(message: str) -> bool:
print(f"BURAZENGIJA SRA CU JA U SHOULD SEARCH TRAVEL INFU")
"""Decide whether to search for travel information based on the message content."""
message_lower = message.lower()
# Keywords that indicate we should search for travel information
travel_keywords = [
"destinacija", "let", "hotel", "putovanje", "mediteran", "grčka", "italija",
"turska", "budžet", "porodica", "all inclusive", "preporučite", "ponuda",
"destination", "flight", "travel", "mediterranean", "greece", "italy",
"turkey", "budget", "family", "recommend", "offer"
]
return any(keyword in message_lower for keyword in travel_keywords)
def chat_with_turbot(message: str, history: List[List[str]]) -> str:
print(f"BURAZ KOJI JE OVO KITA MOJA")
"""
Main function to chat with TurBot.
"""
# Prepare the system message first
system_message = """Ti si TurBot, digitalni asistent za turističku agenciju.
Odgovori na srpskom jeziku i budi koristan i prijateljski nastrojen.
Ako ne znaš odgovor na pitanje, preporuči korisniku da pita o putovanjima, letovima, hotelima ili destinacijama."""
# Convert messages to the format expected by InferenceClient
messages_for_client = []
# Add system message first (only once per interaction, model will handle context)
messages_for_client.append({"role": "system", "content": system_message})
# Add conversation history
for human, ai in history:
if human:
messages_for_client.append({"role": "user", "content": human})
if ai:
messages_for_client.append({"role": "assistant", "content": ai})
# Add the current message
messages_for_client.append({"role": "user", "content": message})
# Check if we should search for travel information
context = ""
if should_search_travel_info(message):
context = search_travel_packages(message)
if context:
# Add context as additional information for the model
# It's better to add it as a user message or a tool output for the model to use
messages_for_client.append({"role": "user", "content": f"Relevantne informacije iz baze podataka: {context}"})
try:
# Debug: Print messages being sent to model
print(f"\n🔍 DEBUG: Sending {len(messages_for_client)} messages to model:")
for i, msg in enumerate(messages_for_client):
print(f" {i+1}. {msg['role']}: {msg['content'][:150]}...") # Povećan prikaz karaktera za debug
# Generate response
response = ""
# The `client.chat_completion` now expects `messages` in a list of dicts.
# This is already correctly prepared as `messages_for_client`.
for message_chunk in client.chat_completion(
messages_for_client, # Prosleđujemo celu listu poruka
stream=True,
max_tokens=512,
temperature=0.7,
top_p=0.95,
):
if hasattr(message_chunk, 'choices') and message_chunk.choices:
token = message_chunk.choices[0].delta.content
if token:
response += token
return response if response else "Izvinjavam se, nisam dobio odgovor od modela. Pokušajte ponovo."
except Exception as e:
return f"Izvinjavam se, došlo je do greške u pozivu LLM-a: {str(e)}"