Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Design and add a MongoDB schema (Issue 75) #100

Closed
wants to merge 9 commits into from
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ venv/
.mypy_cache/
.vscode/
.venv
.DS_Store

# docs
documents.txt
credentials.json

# virtualenv
.venv
Expand Down
1 change: 0 additions & 1 deletion backend/src/api/main.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from fastapi import FastAPI

from .routers import graphs, healthcheck

app = FastAPI()
Expand Down
1 change: 1 addition & 0 deletions common/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
MONGO_DB_URI = YOUR_MONGO_DB_URI
151 changes: 151 additions & 0 deletions common/mongoClient.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
from pymongo import MongoClient
from pymongo.database import Database
from dotenv import load_dotenv
import os

load_dotenv()

# HARDCODED collection names
feedback_collection_name = "feedback"
context_collection_name = "context"

def get_mongo_db_client() -> Database:
"""
Get the MongoDB client.
Returns:
- DatabaseClient: The Database client.
Note:
MongoDB doesn't create a collection or a database until it gets content, so no need to check if the data already exists or not.
"""

uri = os.getenv("MONGO_DB_URI")
client = MongoClient(uri)
# this is the database that is returned by the client
return client["feedback_db"]

def submit_feedback():
"""
Submit feedback Record to the MongoDB database.
Args:
- question (str): The question for which feedback is being submitted.
- answer (str): The generated answer to the question.
- sources (list[str]): Source data used for the answer.
- context (list[str]): Additional context from the RAG.
- issue (str): Details about the issue.
- version (str): Version information.
Returns:
- None
"""

feedback_db_client = get_mongo_client()

try:
if not check_collection_exists(feedback_collection_name,feedback_db_client,):
create_collection(feedback_collection_name,feedback_db_client, validator={
'$jsonSchema': {
'bsonType': 'object',
'required': ['question', 'answer', 'sources', 'context_ids', 'issue', 'version', 'timestamp'],
'properties': {
'question': {
'bsonType': 'string',
'description': 'must be a string and is required'
},
'answer': {
'bsonType': 'string',
'description': 'must be a string and is required'
},
'sources': {
'bsonType': 'array',
'items': {
'bsonType': 'objectId'
},
'description': 'must be an array of ObjectIds referencing the sources and is required'
},
'context': {
'bsonType': 'array',
'items': {
'bsonType': 'string'
},
'description': 'must be an array of strings and is required'
},
'issue': {
'bsonType': 'string',
'description': 'must be a string and is required'
},
'version': {
'bsonType': 'string',
'description': 'must be a string and is required'
},
'timestamp': {
'bsonType': 'date',
'description': 'must be a date and is required'
},
'status': {
'enum': ['new', 'processing', 'resolved'],
'description': 'can only be one of the enum values'
}
}
}
})
if not check_collection_exists(context_collection_name,feedback_db_client):
create_collection(context_collection_name,feedback_db_client,{
'bsonType': 'object',
'required': ['source', 'timestamp'],
'properties': {
'source': {
'bsonType': 'string',
'description': 'must be a string and is required'
},
'metadata': {
'bsonType': 'object',
'description': 'additional metadata for the context'
},
'timestamp': {
'bsonType': 'date',
'description': 'must be a date and is required'
}
}
}
)

except Exception as e:
print(f"Failed to submit feedback: {e}")
return None

def check_collection_exists(collection_name:str,client_database:Database)->bool:
"""
Check if the collection exists in the database.
Args:
- collection_name (str): The name of the collection to check.
- client_database (Database): The database to check.
Returns:
- None
"""
return collection_name in client_database.list_collection_names()

def create_collection(collection_name:str,client_database:Database,validator:object)->None:
"""
Create a collection in the database.
Args:
- collection_name (str): The name of the collection to create.
- client_database (Database): The database to create the collection in.
Returns:
- None
"""
try:
client_database.create_collection(collection_name,validator=validator)
print("Collection created successfully")
except Exception as e:
print(f"Failed to create collection: {e}")
return None

if __name__ == "__main__":
submit_feedback()
2 changes: 2 additions & 0 deletions common/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pymongo==4.6.2
python-dotenv==1.0.1
2 changes: 1 addition & 1 deletion frontend/streamlit_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ def update_state() -> None:
question_dict,
st.session_state.metadata,
st.session_state.chat_history,
)
)
except Exception as e:
st.error(f"Failed to load feedback form: {e}")

Expand Down
16 changes: 12 additions & 4 deletions frontend/utils/feedback.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ def submit_feedback_to_google_sheet(
]

creds = Credentials.from_service_account_file(service_account_file, scopes=scope)
# this is the place where the client is coming from, need to change this for mongoDB client
client = gspread.authorize(creds)

sheet_id = os.getenv("FEEDBACK_SHEET_ID", "")
Expand Down Expand Up @@ -170,8 +171,15 @@ def show_feedback_form(
feedback = st.sidebar.text_area("Please provide your feedback or report an issue:")

if selected_question:
sources = [metadata[selected_question].get("sources", "N/A")]
context = [metadata[selected_question].get("context", "N/A")]
sources = metadata[selected_question].get("sources", ["N/A"])
Kannav02 marked this conversation as resolved.
Show resolved Hide resolved
if isinstance(sources, str):

sources = [sources]

context = metadata[selected_question].get("context", ["N/A"])
if isinstance(context, str):

context = [context]

if st.sidebar.button("Submit"):
selected_index = questions[selected_question]
Expand All @@ -180,8 +188,8 @@ def show_feedback_form(
submit_feedback_to_google_sheet(
question=selected_question,
answer=gen_ans,
sources=sources,
context=context,
sources=sources, # Now passing as list
context=context, # Now passing as list
issue=feedback,
version=os.getenv("RAG_VERSION", get_git_commit_hash()),
)
Expand Down
Loading