Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
E
ecom-svc-reviewsense
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Bhargava Rellu
ecom-svc-reviewsense
Commits
c05bf261
Commit
c05bf261
authored
Mar 31, 2025
by
Bhargava Rellu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
remove the chatbot code
parent
b1dc058d
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
17 additions
and
279 deletions
+17
-279
.env
.env
+1
-1
llm.py
src/reviewsense_ecom/llm/llm.py
+1
-77
routes.py
src/reviewsense_ecom/router/routes.py
+14
-30
BotService.py
src/reviewsense_ecom/service/BotService.py
+0
-170
feature_extractor.py
src/reviewsense_ecom/service/feature_extractor.py
+1
-1
No files found.
.env
View file @
c05bf261
...
@@ -2,5 +2,5 @@ ASTRA_DB_API_ENDPOINT="https://0c52512b-0c65-4e70-ac47-71edf5244a82-us-east-2.ap
...
@@ -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_APPLICATION_TOKEN="AstraCS:EvXpFFafufegdQJvhqlYxmxt:ef86b5996013b12140b69254bd554d7e8e10eb5a7137859b9c432f92a5a3b65c"
ASTRA_DB_NAMESPACE="default_keyspace"
ASTRA_DB_NAMESPACE="default_keyspace"
HF_TOKEN="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"
HF_TOKEN="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"
GROQ_API_KEY="gsk_
w8cmZPxfwBO0NVqAqFjZWGdyb3FY4B3ZE1aIOK60auWtkmTu32b
e"
GROQ_API_KEY="gsk_
DDIpC0VKSeRBpEOER3F9WGdyb3FY3Nbcl3GmfyEsFcB3nm5hmca
e"
MONGODB_URL=mongodb+srv://genai:nisum@123@productrater.hpbsn.mongodb.net/?retryWrites=true&w=majority&appName=productRater
MONGODB_URL=mongodb+srv://genai:nisum@123@productrater.hpbsn.mongodb.net/?retryWrites=true&w=majority&appName=productRater
src/reviewsense_ecom/llm/llm.py
View file @
c05bf261
...
@@ -4,6 +4,7 @@ from functools import lru_cache
...
@@ -4,6 +4,7 @@ from functools import lru_cache
from
langchain_core.messages
import
BaseMessage
from
langchain_core.messages
import
BaseMessage
from
langchain_core.prompts
import
ChatPromptTemplate
from
langchain_core.prompts
import
ChatPromptTemplate
@
lru_cache
(
maxsize
=
1
)
# Cache only one instance (singleton behavior)
@
lru_cache
(
maxsize
=
1
)
# Cache only one instance (singleton behavior)
def
get_llm
(
groq_token
:
str
):
def
get_llm
(
groq_token
:
str
):
"""
"""
...
@@ -15,85 +16,8 @@ def get_llm(groq_token: str):
...
@@ -15,85 +16,8 @@ def get_llm(groq_token: str):
Returns:
Returns:
ChatGroq: A singleton instance of the ChatGroq LLM.
ChatGroq: A singleton instance of the ChatGroq LLM.
"""
"""
groq_token
=
"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"
return
ChatGroq
(
return
ChatGroq
(
model_name
=
"llama-3.3-70b-versatile"
,
model_name
=
"llama-3.3-70b-versatile"
,
temperature
=
1
,
temperature
=
1
,
groq_api_key
=
groq_token
# Pass the Groq token here
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."
src/reviewsense_ecom/router/routes.py
View file @
c05bf261
import
logging
import
logging
from
fastapi
import
APIRouter
,
HTTPException
from
fastapi
import
APIRouter
,
HTTPException
from
src.reviewsense_ecom.model.PercentageResponseModel
import
PercentageResponseModel
from
src.reviewsense_ecom.model.PercentageResponseModel
import
PercentageResponseModel
from
src.reviewsense_ecom.model.ReviewResponseModel
import
ReviewResponseModel
from
src.reviewsense_ecom.model.ReviewResponseModel
import
ReviewResponseModel
from
src.reviewsense_ecom.service.FeatureUpdater
import
FeatureUpdater
from
src.reviewsense_ecom.service.FeatureUpdater
import
FeatureUpdater
from
src.reviewsense_ecom.model.Product
import
Product
from
src.reviewsense_ecom.model.Product
import
Product
from
src.reviewsense_ecom.service.ReviewService
import
ReviewService
from
src.reviewsense_ecom.service.ReviewService
import
ReviewService
from
src.reviewsense_ecom.service.feature_extractor
import
FeatureExtractor
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.product_review_input
import
ProductReviewInput
from
src.reviewsense_ecom.model.UserMessage
import
UserMessage
from
src.reviewsense_ecom.service.BotService
import
BotService
router
=
APIRouter
()
router
=
APIRouter
()
review_service
=
ReviewService
()
review_service
=
ReviewService
()
...
@@ -21,6 +18,7 @@ feature_extractor = FeatureExtractor()
...
@@ -21,6 +18,7 @@ feature_extractor = FeatureExtractor()
logger
=
logging
.
getLogger
(
__name__
)
logger
=
logging
.
getLogger
(
__name__
)
@
router
.
post
(
"/calculate_ratings/"
,
response_model
=
Product
)
@
router
.
post
(
"/calculate_ratings/"
,
response_model
=
Product
)
async
def
calculate_ratings
(
input_data
:
ProductReviewInput
):
# Required
async
def
calculate_ratings
(
input_data
:
ProductReviewInput
):
# Required
"""
"""
...
@@ -56,14 +54,15 @@ 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}"
)
logger
.
info
(
f
"Product Data: {product_data}"
)
final_product
=
product_data
final_product
=
product_data
if
input_data
.
is_rating_evaluation_required
:
if
input_data
.
is_rating_evaluation_required
:
final_product
=
await
update_product_data
(
input_data
,
product_data
)
final_product
=
await
update_product_data
(
input_data
,
product_data
)
logger
.
info
(
f
"Final Return to Mongo: {final_product}"
)
logger
.
info
(
f
"Final Return to Mongo: {final_product}"
)
return
final_product
return
final_product
@
router
.
get
(
"/fetch_percentage/"
,
response_model
=
PercentageResponseModel
)
@
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.
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
...
@@ -74,8 +73,9 @@ async def fetch_percentage(product_id: str, features: str): #NOT REQUIRED
return
{
"message"
:
"No data found"
}
return
{
"message"
:
"No data found"
}
@
router
.
get
(
"/fetch_reviews/"
,
response_model
=
ReviewResponseModel
)
@
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.
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
...
@@ -85,8 +85,10 @@ async def fetch_review_by_feature(product_id: str, features: str): #NotRequired
return
reviews
return
reviews
return
{
"reviews"
:
reviews
}
return
{
"reviews"
:
reviews
}
@
router
.
get
(
"/fetch_full_reviews/"
,
response_model
=
ReviewResponseModel
)
@
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.
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
...
@@ -97,13 +99,13 @@ async def fetch_review_by_feature(product_id: str, features: str): #Required
return
{
"reviews"
:
reviews
}
return
{
"reviews"
:
reviews
}
async
def
update_product_data
(
input_data
,
product_data
):
async
def
update_product_data
(
input_data
,
product_data
):
# ✅ Second Flow: Update Feature Ratings in Another Collection FROM LLM
# ✅ 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
(
reviews_by_feature
=
feature_extractor
.
extract_feature_reviews
(
input_data
.
new_review
,
features
)
input_data
.
new_review
,
features
)
ratings
=
review_service
.
fetch_feature_ratings
(
reviews_by_feature
)
ratings
=
review_service
.
fetch_feature_ratings
(
reviews_by_feature
)
logger
.
info
(
f
"Generated ratings: {ratings}"
)
logger
.
info
(
f
"Generated ratings: {ratings}"
)
# ✅ First Flow: Add Review to a Separate Collection TO REVIEWS
# ✅ First Flow: Add Review to a Separate Collection TO REVIEWS
...
@@ -125,21 +127,3 @@ async def update_product_data(input_data, product_data):
...
@@ -125,21 +127,3 @@ async def update_product_data(input_data, product_data):
logger
.
error
(
"update_product() returned None. Update failed."
)
logger
.
error
(
"update_product() returned None. Update failed."
)
raise
HTTPException
(
status_code
=
500
,
detail
=
"Failed to update product"
)
raise
HTTPException
(
status_code
=
500
,
detail
=
"Failed to update product"
)
return
final_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
}
src/reviewsense_ecom/service/BotService.py
deleted
100644 → 0
View file @
b1dc058d
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."
src/reviewsense_ecom/service/feature_extractor.py
View file @
c05bf261
...
@@ -20,7 +20,7 @@ class FeatureExtractor:
...
@@ -20,7 +20,7 @@ class FeatureExtractor:
api_key
=
os
.
getenv
(
'GROQ_API_KEY'
)
api_key
=
os
.
getenv
(
'GROQ_API_KEY'
)
if
not
api_key
:
if
not
api_key
:
raise
ValueError
(
"GROQ_API_KEY is not set in the environment variables."
)
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
.
parser
=
self
.
_create_reviews_parser
()
self
.
prompt
=
self
.
_create_extraction_prompt
()
self
.
prompt
=
self
.
_create_extraction_prompt
()
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment