Commit c05bf261 authored by Bhargava Rellu's avatar Bhargava Rellu

remove the chatbot code

parent b1dc058d
......@@ -2,5 +2,5 @@ ASTRA_DB_API_ENDPOINT="https://0c52512b-0c65-4e70-ac47-71edf5244a82-us-east-2.ap
ASTRA_DB_APPLICATION_TOKEN="AstraCS:EvXpFFafufegdQJvhqlYxmxt:ef86b5996013b12140b69254bd554d7e8e10eb5a7137859b9c432f92a5a3b65c"
ASTRA_DB_NAMESPACE="default_keyspace"
HF_TOKEN="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"
GROQ_API_KEY="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"
GROQ_API_KEY="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"
MONGODB_URL=mongodb+srv://genai:nisum@123@productrater.hpbsn.mongodb.net/?retryWrites=true&w=majority&appName=productRater
......@@ -4,6 +4,7 @@ from functools import lru_cache
from langchain_core.messages import BaseMessage
from langchain_core.prompts import ChatPromptTemplate
@lru_cache(maxsize=1) # Cache only one instance (singleton behavior)
def get_llm(groq_token: str):
"""
......@@ -15,85 +16,8 @@ def get_llm(groq_token: str):
Returns:
ChatGroq: A singleton instance of the ChatGroq LLM.
"""
groq_token="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"
return ChatGroq(
model_name="llama-3.3-70b-versatile",
temperature=1,
groq_api_key=groq_token # Pass the Groq token here
)
def generate_response(
query: str,
context: str,
max_context_length: int = 2000
) -> str:
"""
Generate response using LLM for ecommerce product queries.
Args:
query: User query string
context: Context string containing product details and reviews
max_context_length: Maximum allowed length for context
Returns:
Generated response string
Raises:
ValueError: If input parameters are invalid
Exception: For other processing errors
"""
# Input validation
if not query or not query.strip():
raise ValueError("Query cannot be empty")
if not context or not context.strip():
raise ValueError("Context cannot be empty")
try:
# Preprocess context
context = context.strip()
if len(context) > max_context_length:
context = context[:max_context_length] + "..."
llm_template = """
Your task is to act as an ecommerce product expert assistant.
Analyze the provided product information and reviews carefully.
Guidelines:
- Provide accurate product-specific information based on the context
- Keep responses concise and focused on the query
- Include relevant product features and customer feedback
- If information is not in the context, acknowledge the limitation
- Maintain a helpful and professional tone
CONTEXT:
{context}
QUESTION: {input}
YOUR ANSWER:
"""
# Create and execute the chain
chain = ChatPromptTemplate.from_template(llm_template) | get_llm()
result = chain.invoke({
"context": context,
"input": query
})
# Extract response text based on message type
if isinstance(result, BaseMessage):
response = result.content
elif isinstance(result, str):
response = result
else:
response = str(result)
# Validate response
if not response or not response.strip():
raise ValueError("Empty response received from LLM")
return response.strip()
except Exception as e:
return "I apologize, but I encountered an error while processing your request. Please try again or contact support if the issue persists."
import logging
from fastapi import APIRouter, HTTPException
from src.reviewsense_ecom.model.PercentageResponseModel import PercentageResponseModel
from src.reviewsense_ecom.model.ReviewResponseModel import ReviewResponseModel
from src.reviewsense_ecom.service.FeatureUpdater import FeatureUpdater
from src.reviewsense_ecom.model.Product import Product
from src.reviewsense_ecom.service.ReviewService import ReviewService
from src.reviewsense_ecom.service.feature_extractor import FeatureExtractor
from src.reviewsense_ecom.mongo.mongo_db_config import get_product_by_id, update_product, add_review_features, insert_product,product_feature
from src.reviewsense_ecom.mongo.mongo_db_config import get_product_by_id, update_product, add_review_features, \
insert_product, product_feature
from src.reviewsense_ecom.model.product_review_input import ProductReviewInput
from src.reviewsense_ecom.model.UserMessage import UserMessage
from src.reviewsense_ecom.service.BotService import BotService
router = APIRouter()
review_service = ReviewService()
......@@ -21,6 +18,7 @@ feature_extractor = FeatureExtractor()
logger = logging.getLogger(__name__)
@router.post("/calculate_ratings/", response_model=Product)
async def calculate_ratings(input_data: ProductReviewInput): # Required
"""
......@@ -56,14 +54,15 @@ async def calculate_ratings(input_data: ProductReviewInput): # Required
logger.info(f"Product Data: {product_data}")
final_product = product_data
if input_data.is_rating_evaluation_required :
final_product = await update_product_data( input_data, product_data)
if input_data.is_rating_evaluation_required:
final_product = await update_product_data(input_data, product_data)
logger.info(f"Final Return to Mongo: {final_product}")
return final_product
@router.get("/fetch_percentage/", response_model=PercentageResponseModel)
async def fetch_percentage(product_id: str, features: str): #NOT REQUIRED
async def fetch_percentage(product_id: str, features: str): # NOT REQUIRED
"""
Fetch reviews from MongoDB based on product_id and feature.
"""
......@@ -74,8 +73,9 @@ async def fetch_percentage(product_id: str, features: str): #NOT REQUIRED
return {"message": "No data found"}
@router.get("/fetch_reviews/", response_model=ReviewResponseModel)
async def fetch_review_by_feature(product_id: str, features: str): #NotRequired
async def fetch_review_by_feature(product_id: str, features: str): # NotRequired
"""
Fetch reviews from MongoDB based on product_id and feature.
"""
......@@ -85,8 +85,10 @@ async def fetch_review_by_feature(product_id: str, features: str): #NotRequired
return reviews
return {"reviews": reviews}
@router.get("/fetch_full_reviews/", response_model=ReviewResponseModel)
async def fetch_review_by_feature(product_id: str, features: str): #Required
async def fetch_review_by_feature(product_id: str, features: str): # Required
"""
Fetch reviews from MongoDB based on product_id and feature.
"""
......@@ -97,13 +99,13 @@ async def fetch_review_by_feature(product_id: str, features: str): #Required
return {"reviews": reviews}
async def update_product_data(input_data, product_data):
# ✅ Second Flow: Update Feature Ratings in Another Collection FROM LLM
features=product_feature(input_data.product_id)
features = product_feature(input_data.product_id)
reviews_by_feature = feature_extractor.extract_feature_reviews(
input_data.new_review, features)
ratings = review_service.fetch_feature_ratings(reviews_by_feature)
logger.info(f"Generated ratings: {ratings}")
# ✅ First Flow: Add Review to a Separate Collection TO REVIEWS
......@@ -125,21 +127,3 @@ async def update_product_data(input_data, product_data):
logger.error("update_product() returned None. Update failed.")
raise HTTPException(status_code=500, detail="Failed to update product")
return final_product
#ChatBotAPI
@router.post("/chat")
async def chat(user_message: UserMessage):
"""
Endpoint to handle user messages and return chatbot responses.
"""
if not user_message.message:
raise HTTPException(status_code=400, detail="Message cannot be empty")
bot_service = BotService()
# Handle a query
response = bot_service.handle_user_query(user_message.message)
# Or use individual components
return {"response": response}
from dataclasses import dataclass
from typing import List, Dict, Optional, Tuple, Any
from langchain_astradb import AstraDBVectorStore
from logging import getLogger
from functools import lru_cache
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import ChatPromptTemplate
from src.reviewsense_ecom.llm.llm import get_llm, generate_response
from src.reviewsense_ecom.retriever.retrieval import get_vector_store
logger = getLogger(__name__)
@dataclass
class ProductContext:
product_name: str
product_reviews: str
class BotServiceError(Exception):
"""Base exception for bot service errors"""
pass
class VectorStoreError(BotServiceError):
"""Exception for vector store related errors"""
pass
class ReviewProcessor:
@staticmethod
def clean_review(review: str) -> str:
"""Clean and format a single review"""
return review.strip() + ('.' if not review.strip().endswith('.') else '')
@staticmethod
def process_reviews(doc_content: str) -> List[str]:
"""Process document content into cleaned review sentences"""
return [
ReviewProcessor.clean_review(sentence)
for sentence in doc_content.split('.')
if sentence.strip()
]
class BotService:
def __init__(self, vector_store: Optional[AstraDBVectorStore] = None):
self.vector_store = vector_store or self._initialize_vector_store()
self.llm = get_llm()
@staticmethod
@lru_cache(maxsize=1)
def _initialize_vector_store() -> AstraDBVectorStore:
"""Initialize and cache vector store connection"""
try:
return get_vector_store()
except Exception as e:
logger.error(f"Failed to initialize vector store: {e}")
raise VectorStoreError(f"Vector store initialization failed: {e}")
def get_product_reviews(
self,
product_id: str,
query: str,
k: int = 1
) -> str:
"""
Retrieve and combine product reviews from the vector store.
Args:
product_id: Product identifier
query: Search query
k: Number of results to retrieve
Returns:
Combined review string
"""
try:
results = self.vector_store.similarity_search_with_score_id(
query=query,
k=k,
filter={"product_name": product_id}
)
all_reviews = []
for doc, _, _ in results:
reviews = ReviewProcessor.process_reviews(doc.page_content)
all_reviews.extend(reviews)
return ' '.join(all_reviews)
except Exception as e:
logger.error(f"Error retrieving product reviews: {e}")
raise VectorStoreError(f"Failed to retrieve reviews: {e}")
def retrieve_context(
self,
query: str,
search_query: str,
k: int = 1
) -> Optional[ProductContext]:
"""
Retrieve context from vector store.
Args:
query: User query
search_query: Search query for vector store
k: Number of results to retrieve
Returns:
ProductContext if found, None otherwise
"""
try:
as_retriever = self.vector_store.as_retriever(search_type="similarity_score_threshold",
search_kwargs={"k": 1, "score_threshold": 0.8}, )
results = as_retriever.invoke(search_query)
if not results:
logger.info("No results found for query")
return None
document = results[0]
product_name = document.metadata.get('product_name')
if not product_name:
logger.warning("Product name missing in document metadata")
return None
return ProductContext(
product_name=product_name,
product_reviews=self.get_product_reviews(query=query, product_id=product_name)
)
except Exception as e:
logger.error(f"Error retrieving context: {e}")
raise VectorStoreError(f"Context retrieval failed: {e}")
def handle_user_query(self, query: str) -> str:
"""
Process user query end-to-end.
Args:
query: User query
Returns:
Generated response
"""
try:
context = self.retrieve_context(query=query, search_query=query)
if not context:
return "I'm sorry, I couldn't find relevant information."
formatted_context = f"""Product Information:
Name: {context.product_name}
Customer Reviews:
{context.product_reviews}"""
return generate_response(
query=query,
context=formatted_context
)
except BotServiceError as e:
logger.error(f"Error handling user query: {e}")
return "I apologize, but I encountered an error processing your request."
......@@ -20,7 +20,7 @@ class FeatureExtractor:
api_key = os.getenv('GROQ_API_KEY')
if not api_key:
raise ValueError("GROQ_API_KEY is not set in the environment variables.")
self.llm = get_llm()
self.llm = get_llm(api_key)
self.parser = self._create_reviews_parser()
self.prompt = self._create_extraction_prompt()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment