Vela commited on
Commit
8853856
Β·
1 Parent(s): 74b0947

enhanced frontedn

Browse files
src/backend/api_routes/__pycache__/chat_api.cpython-313.pyc CHANGED
Binary files a/src/backend/api_routes/__pycache__/chat_api.cpython-313.pyc and b/src/backend/api_routes/__pycache__/chat_api.cpython-313.pyc differ
 
src/backend/api_routes/__pycache__/chat_history_supabase_api.cpython-313.pyc CHANGED
Binary files a/src/backend/api_routes/__pycache__/chat_history_supabase_api.cpython-313.pyc and b/src/backend/api_routes/__pycache__/chat_history_supabase_api.cpython-313.pyc differ
 
src/backend/api_routes/__pycache__/knowledge_base_api.cpython-313.pyc CHANGED
Binary files a/src/backend/api_routes/__pycache__/knowledge_base_api.cpython-313.pyc and b/src/backend/api_routes/__pycache__/knowledge_base_api.cpython-313.pyc differ
 
src/backend/api_routes/chat_api.py CHANGED
@@ -1,9 +1,9 @@
1
  from fastapi import APIRouter, HTTPException, status, Depends
2
- from services.embedding_service import get_text_embedding
3
- from services.pinecone_service import retrieve_context_from_pinecone
4
- from services.llm_model_service import get_health_advice
5
- from services.schemas import ConversationInput
6
- from utils import logger
7
 
8
  logger = logger.get_logger()
9
 
 
1
  from fastapi import APIRouter, HTTPException, status, Depends
2
+ from backend.services.embedding_service import get_text_embedding
3
+ from backend.services.pinecone_service import retrieve_context_from_pinecone
4
+ from backend.services.llm_model_service import get_health_advice
5
+ from backend.services.schemas import ConversationInput
6
+ from backend.utils import logger
7
 
8
  logger = logger.get_logger()
9
 
src/backend/api_routes/chat_history_supabase_api.py CHANGED
@@ -1,8 +1,8 @@
1
- from typing import Dict, Any, Union
2
  from fastapi import APIRouter, HTTPException, status, Query
3
- from services.schemas import ChatHistoryRequest
4
- from services import supabase_service
5
- from utils import logger
6
 
7
  logger = logger.get_logger()
8
 
@@ -12,7 +12,7 @@ router = APIRouter(
12
  )
13
 
14
  @router.post('/store', response_model=Dict[str, Any], status_code=status.HTTP_201_CREATED)
15
- def add_chat_history(chat_history: ChatHistoryRequest) -> Dict[str, Any]:
16
  """
17
  Save chat conversation history in the database.
18
 
@@ -50,7 +50,7 @@ def add_chat_history(chat_history: ChatHistoryRequest) -> Dict[str, Any]:
50
  )
51
 
52
  @router.get('/retrieve', response_model=Union[Dict[str, Any], None])
53
- def get_chat_history(
54
  conversation_id: str = Query(..., description="Conversation ID for chat history retrieval")
55
  ) -> Union[Dict[str, Any], None]:
56
  """
@@ -96,4 +96,24 @@ def get_chat_history(
96
  raise HTTPException(
97
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
98
  detail="Unexpected error occurred while retrieving chat history. Please try again later."
99
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Dict,List, Any, Union
2
  from fastapi import APIRouter, HTTPException, status, Query
3
+ from backend.services.schemas import ChatHistoryRequest
4
+ from backend.services import supabase_service
5
+ from backend.utils import logger
6
 
7
  logger = logger.get_logger()
8
 
 
12
  )
13
 
14
  @router.post('/store', response_model=Dict[str, Any], status_code=status.HTTP_201_CREATED)
15
+ async def add_chat_history(chat_history: ChatHistoryRequest) -> Dict[str, Any]:
16
  """
17
  Save chat conversation history in the database.
18
 
 
50
  )
51
 
52
  @router.get('/retrieve', response_model=Union[Dict[str, Any], None])
53
+ async def get_chat_history(
54
  conversation_id: str = Query(..., description="Conversation ID for chat history retrieval")
55
  ) -> Union[Dict[str, Any], None]:
56
  """
 
96
  raise HTTPException(
97
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
98
  detail="Unexpected error occurred while retrieving chat history. Please try again later."
99
+ )
100
+
101
+ @router.get("/bucket-items", response_model=List[str])
102
+ async def retrieve_bucket_items():
103
+ """
104
+ API endpoint to retrieve item names from a specified Supabase storage bucket.
105
+
106
+ Returns:
107
+ List[str]: A list of item names with '.json' removed, excluding the last item in the bucket.
108
+
109
+ Raises:
110
+ HTTPException: If an error occurs while fetching bucket items.
111
+ """
112
+ try:
113
+ conversation_ids = supabase_service.get_bucket_items()
114
+ if conversation_ids:
115
+ return conversation_ids
116
+ else:
117
+ raise HTTPException(status_code=404, detail="No items found in the bucket.")
118
+ except Exception as e:
119
+ raise HTTPException(status_code=500, detail=f"Error fetching bucket items: {e}")
src/backend/api_routes/knowledge_base_api.py CHANGED
@@ -1,8 +1,8 @@
1
  from fastapi import APIRouter, HTTPException
2
- from services import pinecone_service, embedding_service
3
- from services.schemas import UpsertRequest, DeleteRequest, MetadataRequest
4
  import pandas as pd
5
- from utils import logger
6
  from fastapi.responses import JSONResponse
7
 
8
  logger = logger.get_logger()
 
1
  from fastapi import APIRouter, HTTPException
2
+ from backend.services import pinecone_service, embedding_service
3
+ from backend.services.schemas import UpsertRequest, DeleteRequest, MetadataRequest
4
  import pandas as pd
5
+ from backend.utils import logger
6
  from fastapi.responses import JSONResponse
7
 
8
  logger = logger.get_logger()
src/backend/data/dataset.py CHANGED
@@ -1,7 +1,7 @@
1
  import os
2
  import pandas as pd
3
  import string
4
- from utils import logger
5
 
6
  logger = logger.get_logger()
7
 
 
1
  import os
2
  import pandas as pd
3
  import string
4
+ from backend.utils import logger
5
 
6
  logger = logger.get_logger()
7
 
src/backend/data/pinecone_db.py DELETED
@@ -1,230 +0,0 @@
1
- import os
2
- # import sys
3
- # src_directory = os.path.abspath(os.path.join(os.path.dirname(__file__), "../..", "backend"))
4
- # sys.path.append(src_directory)
5
- from pinecone import Pinecone, ServerlessSpec
6
- import time
7
- from tqdm import tqdm
8
- from dotenv import load_dotenv
9
- from utils import logger
10
- import pandas as pd
11
- from models import embedding_model
12
-
13
- load_dotenv()
14
- PINECONE_API_KEY = os.environ.get("PINECONE_API_KEY")
15
- logger = logger.get_logger()
16
- NAMESPACE = "health-care-dataset"
17
- INDEX_NAME = "health-care-index"
18
- PINECONE = Pinecone(api_key=PINECONE_API_KEY)
19
-
20
- def initialize_pinecone_index(pinecone, index_name, dimension=384, metric="cosine", cloud="aws", region="us-east-1"):
21
- """
22
- Retrieves an existing Pinecone index or creates a new one if it does not exist.
23
-
24
- This method checks for the presence of the specified index. If the index does not exist,
25
- it initiates the creation process, waits until the index is ready, and then returns the index.
26
-
27
- Args:
28
- pinecone (Pinecone): Pinecone client instance.
29
- index_name (str): Name of the index to retrieve or create.
30
- dimension (int, optional): Vector dimension for the index. Default is 384.
31
- metric (str, optional): Distance metric for the index. Default is "cosine".
32
- cloud (str, optional): Cloud provider for hosting the index. Default is "aws".
33
- region (str, optional): Region where the index will be hosted. Default is "us-east-1".
34
-
35
- Returns:
36
- pinecone.Index: The Pinecone index instance.
37
-
38
- Raises:
39
- Exception: If an error occurs during index creation or retrieval.
40
-
41
- Example:
42
- >>> index = get_or_create_index(pinecone, "sample_index")
43
- Logs: "Index 'sample_index' is ready and accessible."
44
- """
45
- try:
46
- logger.info(f"Checking if the index '{index_name}' exists...")
47
-
48
- # Check if index already exists
49
- if not pinecone.has_index(index_name):
50
- logger.info(f"Index '{index_name}' does not exist. Creating a new index...")
51
-
52
- # Create a new index
53
- pinecone.create_index(
54
- name=index_name,
55
- dimension=dimension,
56
- metric=metric,
57
- spec=ServerlessSpec(cloud=cloud, region=region)
58
- )
59
- logger.info(f"Index '{index_name}' creation initiated. Waiting for it to be ready...")
60
-
61
- # Wait until index is ready
62
- while True:
63
- index_status = pinecone.describe_index(index_name)
64
- if index_status.status.get("ready", False):
65
- index = pinecone.Index(index_name)
66
- logger.info(f"Index '{index_name}' is ready and accessible.")
67
- return index
68
- else:
69
- logger.debug(f"Index '{index_name}' is not ready yet. Checking again in 1 second.")
70
- time.sleep(1)
71
- else:
72
- # Return the existing index
73
- index = pinecone.Index(index_name)
74
- logger.info(f"Index '{index_name}' already exists. Returning the existing index.")
75
- return index
76
-
77
- except Exception as e:
78
- logger.error(f"Error occurred while getting or creating the Pinecone index: {str(e)}", exc_info=True)
79
- return None
80
-
81
- def delete_records_by_ids(ids_to_delete):
82
- """
83
- Deletes specified IDs from the database index.
84
-
85
- This method interacts with the index to delete entries based on the provided list of IDs.
86
- It logs a success message if the deletion is successful or returns an error message if it fails.
87
-
88
- Args:
89
- ids_to_delete (list):
90
- A list of unique identifiers (IDs) to be deleted from the database.
91
-
92
- Returns:
93
- str: A success message is logged upon successful deletion.
94
- If an error occurs, a string describing the failure is returned.
95
-
96
- Raises:
97
- Exception: Logs an error if the deletion process encounters an issue.
98
-
99
- Example:
100
- >>> remove_ids_from_database(['id_123', 'id_456'])
101
- Logs: "IDs deleted successfully."
102
-
103
- Notes:
104
- - The method assumes `get_index()` initializes the index object.
105
- - Deletion occurs within the specified `NAMESPACE`.
106
- """
107
- try:
108
- index = initialize_pinecone_index(PINECONE,INDEX_NAME)
109
- index.delete(ids=ids_to_delete, namespace=NAMESPACE)
110
- logger.info("IDs deleted successfully.")
111
- except Exception as e:
112
- return f"Failed to delete the IDs: {e}"
113
-
114
- def retrieve_relevant_metadata(prompt, n_result=3, score_threshold=0.47):
115
- """
116
- Retrieves relevant context data based on a given prompt and extracts metadata.
117
-
118
- This method queries the Pinecone index with the provided prompt's embedding,
119
- fetches the top `n_result` entries, and filters out entries with a score below
120
- the specified threshold. Extracted metadata is formatted and returned.
121
-
122
- Args:
123
- prompt (str or list):
124
- The input prompt used to generate the text embedding.
125
- If a list is provided, the method extracts the last element.
126
- n_result (int, optional):
127
- The number of relevant results to return. Defaults to 3.
128
- score_threshold (float, optional):
129
- The minimum score required for an entry to be included in the results. Defaults to 0.5.
130
-
131
- Returns:
132
- list: A list of dictionaries containing:
133
- - `"question"` (str): Extracted question or `"N/A"` if unavailable.
134
- - `"answer"` (str): Extracted answer or `"N/A"` if unavailable.
135
- - `"instruction"` (str): Extracted instruction or `"N/A"` if unavailable.
136
- - `"score"` (str): The score value as a string for consistency.
137
-
138
- If no relevant entries are found, the list will contain a single
139
- dictionary with the key `"response"` and a message indicating no data was found.
140
-
141
- Example:
142
- >>> prompt = ["Tell me about mental health"]
143
- >>> fetch_and_extract_metadata(prompt, n_result=2)
144
- [{'question': 'What is mental health?', 'answer': 'Mental health refers to...',
145
- 'instruction': 'Focus on general well-being.', 'score': '0.6'}]
146
-
147
- Notes:
148
- - Assumes `get_or_create_index()` initializes the index object.
149
- - Uses `embedding_model.get_text_embedding()` to generate text embeddings.
150
- - Entries without a `metadata` key or with missing fields default to `"N/A"`.
151
- - Entries with a score below `score_threshold` are excluded from results.
152
- """
153
- try:
154
- index = initialize_pinecone_index(PINECONE, INDEX_NAME)
155
- prompt = prompt[-1] if isinstance(prompt, list) else prompt
156
-
157
- # Generate embedding for the provided prompt
158
- embedding = embedding_model.get_text_embedding(prompt)
159
- response = index.query(
160
- top_k=n_result,
161
- vector=embedding,
162
- namespace=NAMESPACE,
163
- include_metadata=True
164
- )
165
-
166
- # Extract and filter metadata
167
- metadata = [
168
- {
169
- "question": entry.get('metadata', {}).get('question', 'N/A'),
170
- "answer": entry.get('metadata', {}).get('answer', 'N/A'),
171
- "instruction": entry.get('metadata', {}).get('instruction', 'N/A'),
172
- "score": f"{entry.get('score', 0)}",
173
- "id": f"{entry.get('id', 'N/A')}"
174
- }
175
- for entry in response.get('matches', [])
176
- if entry.get('score', 0) >= score_threshold
177
- ]
178
-
179
- # Return metadata or fallback message
180
- return metadata if metadata else [{"response": "No relevant data found."}]
181
-
182
- except Exception as e:
183
- logger.error(f"Failed to fetch context for '{prompt[:20]}'. Error: {e}")
184
- return [{"response": "Failed to fetch data due to an error."}]
185
-
186
- def upsert_vector_data(df: pd.DataFrame):
187
-
188
- """
189
- Generates embeddings for the given DataFrame and uploads data to Pinecone in batches.
190
-
191
- Parameters:
192
- - df (pd.DataFrame): DataFrame containing 'input', 'question', and 'answer' columns.
193
-
194
- Returns:
195
- - None
196
- """
197
-
198
- try:
199
- index = initialize_pinecone_index(PINECONE,INDEX_NAME)
200
- df["embedding"] = [
201
- embedding_model.get_text_embedding([q])[0]
202
- for q in tqdm(df["input"], desc="Generating Embeddings")
203
- ]
204
- except Exception as e:
205
- logger.error(f"Error generating embeddings: {e}")
206
- return
207
-
208
- # # Upload data to Pinecone in batches
209
- BATCH_SIZE = 500
210
-
211
- for i in tqdm(range(0, len(df), BATCH_SIZE), desc="Uploading Data to Pinecone"):
212
- batch = df.iloc[i : i + BATCH_SIZE]
213
-
214
- vectors = []
215
- for idx, (embedding, (_, row_data)) in enumerate(zip(batch["embedding"], batch.iterrows())):
216
- question = row_data.get("input")
217
- vector_id = f"{question[:50]}:{i + idx}" # Ensures IDs remain unique across
218
- metadata = {
219
- "question": row_data.get("input"),
220
- "answer": row_data.get("output"),
221
- "instruction": row_data.get("instruction"),
222
- }
223
- vectors.append((vector_id, embedding, metadata))
224
-
225
- try:
226
- index.upsert(vectors=vectors,namespace=NAMESPACE)
227
- except Exception as e:
228
- logger.error(f"Error uploading batch starting at index {i}: {e}")
229
-
230
- logger.info("All question-answer pairs stored successfully!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/backend/services/__pycache__/embedding_service.cpython-313.pyc CHANGED
Binary files a/src/backend/services/__pycache__/embedding_service.cpython-313.pyc and b/src/backend/services/__pycache__/embedding_service.cpython-313.pyc differ
 
src/backend/services/__pycache__/pinecone_service.cpython-313.pyc CHANGED
Binary files a/src/backend/services/__pycache__/pinecone_service.cpython-313.pyc and b/src/backend/services/__pycache__/pinecone_service.cpython-313.pyc differ
 
src/backend/services/__pycache__/supabase_service.cpython-313.pyc CHANGED
Binary files a/src/backend/services/__pycache__/supabase_service.cpython-313.pyc and b/src/backend/services/__pycache__/supabase_service.cpython-313.pyc differ
 
src/backend/services/embedding_service.py CHANGED
@@ -1,6 +1,6 @@
1
  from sentence_transformers import SentenceTransformer
2
  from langchain.text_splitter import RecursiveCharacterTextSplitter
3
- from utils import logger
4
 
5
  logger = logger.get_logger()
6
 
 
1
  from sentence_transformers import SentenceTransformer
2
  from langchain.text_splitter import RecursiveCharacterTextSplitter
3
+ from backend.utils import logger
4
 
5
  logger = logger.get_logger()
6
 
src/backend/services/pinecone_service.py CHANGED
@@ -6,9 +6,9 @@ from pinecone import Pinecone, ServerlessSpec
6
  import time
7
  from tqdm import tqdm
8
  from dotenv import load_dotenv
9
- from utils import logger
10
  import pandas as pd
11
- from services.embedding_service import get_text_embedding
12
  from sentence_transformers import CrossEncoder
13
 
14
  reranker = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')
 
6
  import time
7
  from tqdm import tqdm
8
  from dotenv import load_dotenv
9
+ from backend.utils import logger
10
  import pandas as pd
11
+ from backend.services.embedding_service import get_text_embedding
12
  from sentence_transformers import CrossEncoder
13
 
14
  reranker = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')
src/backend/services/supabase_service.py CHANGED
@@ -1,8 +1,11 @@
1
  import json
2
  import os
 
 
 
3
  from datetime import datetime
4
  from supabase import create_client, StorageException
5
- from utils import logger
6
  from dotenv import load_dotenv
7
 
8
  # Logger Initialization
@@ -14,6 +17,7 @@ SUPABASE_URL = os.getenv('SUPABASE_URL')
14
  SUPABASE_KEY = os.getenv('SUPABASE_KEY')
15
  SUPABASE_BUCKET = os.getenv('SUPABASE_BUCKET')
16
  LLM_MODEL_NAME = os.getenv('LLM_MODEL_NAME')
 
17
 
18
  # Supabase Client Initialization
19
  supabase = create_client(SUPABASE_URL, SUPABASE_KEY)
@@ -137,4 +141,43 @@ def retrieve_chat_history(conversation_id: str) -> dict:
137
  return {"success": False, "error": "Failed to retrieve chat history. Storage error occurred."}
138
  except Exception as e:
139
  logger.error(f"Unexpected error retrieving chat history for ID {conversation_id}: {e}")
140
- return {"success": False, "error": "Unexpected error occurred while retrieving chat history."}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import json
2
  import os
3
+ import sys
4
+ src_directory = os.path.abspath(os.path.join(os.path.dirname(__file__), "../..", "backend"))
5
+ sys.path.append(src_directory)
6
  from datetime import datetime
7
  from supabase import create_client, StorageException
8
+ from backend.utils import logger
9
  from dotenv import load_dotenv
10
 
11
  # Logger Initialization
 
17
  SUPABASE_KEY = os.getenv('SUPABASE_KEY')
18
  SUPABASE_BUCKET = os.getenv('SUPABASE_BUCKET')
19
  LLM_MODEL_NAME = os.getenv('LLM_MODEL_NAME')
20
+ BUCKET_FOLDER = "chat-history"
21
 
22
  # Supabase Client Initialization
23
  supabase = create_client(SUPABASE_URL, SUPABASE_KEY)
 
141
  return {"success": False, "error": "Failed to retrieve chat history. Storage error occurred."}
142
  except Exception as e:
143
  logger.error(f"Unexpected error retrieving chat history for ID {conversation_id}: {e}")
144
+ return {"success": False, "error": "Unexpected error occurred while retrieving chat history."}
145
+
146
+ def get_bucket_items():
147
+ """
148
+ Retrieves item names from a specified Supabase storage bucket and returns them as a list,
149
+ excluding the '.json' extension and omitting the last item in the response.
150
+
151
+ This function uses the globally defined `SUPABASE_BUCKET` and `BUCKET_FOLDER` variables
152
+ to identify the bucket and folder path.
153
+
154
+ Returns:
155
+ list: A list of item names with '.json' removed, excluding the last item in the bucket.
156
+
157
+ Logs:
158
+ - An error if there are no items found in the bucket.
159
+ - An error if an exception occurs during the fetching process.
160
+
161
+ Example:
162
+ Suppose the bucket contains:
163
+ - "2025-03-18.json"
164
+ - "2025-03-19.json"
165
+ - "2025-03-20.json"
166
+
167
+ The function will return:
168
+ ['2025-03-18', '2025-03-19']
169
+
170
+ Raises:
171
+ Exception: Logs an error if fetching bucket items fails.
172
+ """
173
+ try:
174
+ response = supabase.storage.from_(SUPABASE_BUCKET).list(BUCKET_FOLDER)
175
+ conversation_ids = []
176
+ if response:
177
+ for item in response[:-1]:
178
+ conversation_ids.append(item['name'].replace('.json', ''))
179
+ return conversation_ids
180
+ else:
181
+ logger.error("No items found in the bucket.")
182
+ except Exception as e:
183
+ logger.error(f"Error fetching bucket items: {e}")
src/frontend/app/__pycache__/common_functions.cpython-313.pyc CHANGED
Binary files a/src/frontend/app/__pycache__/common_functions.cpython-313.pyc and b/src/frontend/app/__pycache__/common_functions.cpython-313.pyc differ
 
src/frontend/app/__pycache__/pinecone_data_handler.cpython-313.pyc CHANGED
Binary files a/src/frontend/app/__pycache__/pinecone_data_handler.cpython-313.pyc and b/src/frontend/app/__pycache__/pinecone_data_handler.cpython-313.pyc differ
 
src/frontend/app/common_functions.py CHANGED
@@ -2,7 +2,7 @@ import os
2
  import base64
3
  import requests
4
  from dotenv import load_dotenv
5
- from utils import logger
6
  import json
7
  import time
8
  import streamlit as st
@@ -19,9 +19,26 @@ ABOUT_US = "An AI-powered assistant for personalized healthcare guidance."
19
  API_URL = os.getenv("API_URL", "http://localhost:8000")
20
 
21
  def config_homepage(page_title=PAGE_TITLE):
22
- if not hasattr(st, "_page_config_set"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  st.set_page_config(
24
- page_title=PAGE_TITLE,
25
  page_icon=PAGE_ICON,
26
  layout=PAGE_LAYOUT,
27
  initial_sidebar_state="collapsed",
@@ -31,14 +48,41 @@ def config_homepage(page_title=PAGE_TITLE):
31
  "About": ABOUT_US
32
  }
33
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
- def set_page_title(page_title=PAGE_TITLE):
 
 
 
 
36
  st.markdown(f"""
37
- <h1 style="color: white; text-align: left; font-size: 42px;">
38
- <i>{PAGE_TITLE} βš•οΈ</i>
 
 
 
 
 
 
 
 
39
  </h1>
40
- """, unsafe_allow_html=True
41
- )
42
 
43
  def img_to_base64(image_path):
44
  """Convert image to base64."""
@@ -49,16 +93,196 @@ def img_to_base64(image_path):
49
  logger.error(f"Error converting image to base64: {str(e)}")
50
  return None
51
 
52
- def typewriter_effect(text, speed=0.01):
53
- """Displays text with a realistic typewriter effect (character by character)."""
 
 
 
 
 
 
 
 
54
  placeholder = st.empty()
55
  displayed_text = ""
56
-
57
  for char in text:
58
  displayed_text += char
59
- placeholder.markdown(displayed_text)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  time.sleep(speed)
61
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  def get_api_response(endpoint:str, prompt: list):
63
  try:
64
  logger.info(f"Sending user prompt to API endpoint: {API_URL}{endpoint}")
@@ -113,6 +337,47 @@ def store_chat_history_in_db(conversation_id, messages):
113
  except Exception as e:
114
  logger.info(f"Failed to add the chat in db {e}")
115
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  def get_chat_history_from_db(conversation_id: str, retries=3, delay=5):
117
  API_URL = "http://127.0.0.1:8000/chat-history/retrieve"
118
  for attempt in range(retries):
@@ -143,7 +408,7 @@ def display_chat_history(conversation_id):
143
  first_message_content = chat_history["data"]["messages"][0].get('content', '').strip()
144
  button_text = first_message_content[:20] if first_message_content else "No Content"
145
 
146
- if st.sidebar.button(f"Show History for {button_text}", key=f"show_history_{conversation_id}"):
147
  st.subheader(f"Chat History for Conversation ID: {conversation_id}")
148
 
149
  for message in chat_history["data"]["messages"]:
@@ -170,122 +435,11 @@ def display_chat_history(conversation_id):
170
  logger.error(f"Error retrieving chat history for {conversation_id}: {e}")
171
  st.error("An unexpected error occurred while retrieving chat history.")
172
 
173
-
174
- def set_bg_image(file_path, opacity=0.5):
175
- encoded_img = img_to_base64(file_path)
176
- st.markdown(
177
- f"""
178
- <style>
179
- .stApp {{
180
- background: linear-gradient(rgba(0, 0, 0, {opacity}), rgba(0, 0, 0, {opacity})),
181
- url("data:image/png;base64,{encoded_img}") center/cover fixed no-repeat;
182
- min-height: 100vh;
183
- }}
184
- </style>
185
- """,
186
- unsafe_allow_html=True
187
- )
188
-
189
- def custom_navbar():
190
- st.markdown(
191
- """
192
- <style>
193
- .navbar {
194
- display: flex;
195
- justify-content: space-between;
196
- align-items: center;
197
- background-color: #F0F2F6;
198
- padding: 12px 32px;
199
- margin-top: -30px;
200
- width: 100%;
201
- max-width: 1200px;
202
- border-radius: 32px;
203
- box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
204
- border: 1px solid #D1D5DB;
205
- margin-left: auto;
206
- margin-right: auto;
207
- box-sizing: border-box;
208
- flex-wrap: wrap;
209
- }
210
-
211
- .logo {
212
- font-family: 'Arial', sans-serif;
213
- font-size: 30px;
214
- font-weight: bold;
215
- color: #1E293B;
216
- white-space: nowrap;
217
- text-overflow: ellipsis;
218
- flex-wrap: wrap;
219
- }
220
-
221
- .nav-links {
222
- display: flex;
223
- gap: 32px;
224
- align-items: center;
225
- flex-wrap: wrap;
226
- }
227
-
228
- .nav-link {
229
- color: #1E293B !important;
230
- background-color: transparent;
231
- text-decoration: none;
232
- font-weight: 600;
233
- font-size: 18px;
234
- padding: 6px 16px;
235
- border-radius: 8px;
236
- transition: background-color 0.3s ease, color 0.3s ease;
237
- white-space: nowrap;
238
- }
239
-
240
- .nav-link:hover {
241
- background-color: #2E5D5B;
242
- color: #FFFFFF;
243
- }
244
-
245
- @media (max-width: 768px) {
246
- .navbar {
247
- flex-direction: column;
248
- text-align: center;
249
- padding: 12px 16px; /* Adjusted padding for smaller screens */
250
- }
251
-
252
- .nav-links {
253
- flex-direction: column;
254
- gap: 12px;
255
- margin-top: 8px;
256
- }
257
- }
258
-
259
- </style>
260
-
261
- <div class="navbar">
262
- <div class="logo">Yuvabe Care Companion AI</div>
263
- <div class="nav-links">
264
- <a href="/" class="nav-link">Home</a>
265
- <a href="/Admin_Portal" class="nav-link">Admin Portal</a>
266
- <a href="/Knowledge_Base_Explorer" class="nav-link">Knowledge Base Explorer</a>
267
- <a href="/chatbot" class="nav-link">Chat With Us</a>
268
- </div>
269
- </div>
270
- """,
271
- unsafe_allow_html=True
272
- )
273
-
274
- def type_text(container, text, delay=0.03):
275
- """Simulates a typing effect for text with only text highlighted."""
276
- displayed_text = ""
277
- for char in text:
278
- displayed_text += char
279
- container.markdown(f"""
280
- <h2 style="
281
- color: #3D6D6B;
282
- text-align: left;
283
- background: linear-gradient(90deg, #3D6D6B, #6EA8A5);
284
- -webkit-background-clip: text;
285
- color: white;
286
- font-weight: bold;
287
- font-size: 28px;">
288
- {displayed_text}
289
- </h2>
290
- """, unsafe_allow_html=True)
291
- time.sleep(delay)
 
2
  import base64
3
  import requests
4
  from dotenv import load_dotenv
5
+ from frontend.utils import logger
6
  import json
7
  import time
8
  import streamlit as st
 
19
  API_URL = os.getenv("API_URL", "http://localhost:8000")
20
 
21
  def config_homepage(page_title=PAGE_TITLE):
22
+ """
23
+ Configures the Streamlit homepage with essential settings.
24
+
25
+ This function sets up the page title, icon, layout, and sidebar state.
26
+ It also defines custom menu items for better navigation.
27
+
28
+ Args:
29
+ page_title (str): The title displayed on the browser tab (default is PAGE_TITLE).
30
+
31
+ Key Features:
32
+ - Ensures `st.set_page_config()` is called only once to avoid errors.
33
+ - Uses constants for improved maintainability and consistency.
34
+ - Provides links for help, bug reporting, and an 'About' section.
35
+
36
+ Example:
37
+ >>> config_homepage("My Custom App")
38
+ """
39
+ if "page_config_set" not in st.session_state:
40
  st.set_page_config(
41
+ page_title=page_title,
42
  page_icon=PAGE_ICON,
43
  layout=PAGE_LAYOUT,
44
  initial_sidebar_state="collapsed",
 
48
  "About": ABOUT_US
49
  }
50
  )
51
+ st.session_state.page_config_set = True
52
+
53
+ def set_page_title(page_title=PAGE_TITLE, icon="βš•οΈ", color="#2E7D32", font_size="36px"):
54
+ """
55
+ Sets a custom-styled page title for the Streamlit application.
56
+
57
+ Parameters:
58
+ -----------
59
+ page_title : str
60
+ The text to display as the page title. Defaults to the value of PAGE_TITLE.
61
+ icon : str, optional
62
+ An optional emoji or symbol to enhance the visual appeal of the title. Defaults to "βš•οΈ".
63
+ color : str, optional
64
+ Hex color code for the title text. Defaults to a fresh green shade (#2E7D32).
65
+ font_size : str, optional
66
+ Font size for the title text. Defaults to "36px".
67
 
68
+ Example Usage:
69
+ ---------------
70
+ set_page_title("Welcome to Yuvabe", icon="🌿", color="#1E88E5", font_size="42px")
71
+ """
72
+
73
  st.markdown(f"""
74
+ <h1 style="
75
+ color: {color};
76
+ font-size: {font_size};
77
+ font-weight: bold;
78
+ margin-bottom: 15px;
79
+ text-align: center;
80
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2); /* Adds depth for a cleaner look */
81
+ padding: 10px 0; /* Improved spacing */
82
+ ">
83
+ <i>{page_title} {icon}</i>
84
  </h1>
85
+ """, unsafe_allow_html=True)
 
86
 
87
  def img_to_base64(image_path):
88
  """Convert image to base64."""
 
93
  logger.error(f"Error converting image to base64: {str(e)}")
94
  return None
95
 
96
+ def typewriter_effect(text, speed=0.03, gradient=False):
97
+ """
98
+ Displays text with a typewriter effect.
99
+ Supports optional gradient styling for enhanced visual appeal.
100
+
101
+ Args:
102
+ text (str): The text to display with the typing effect.
103
+ speed (float): Typing speed in seconds (default 0.03).
104
+ gradient (bool): If True, applies a gradient effect to the text.
105
+ """
106
  placeholder = st.empty()
107
  displayed_text = ""
108
+
109
  for char in text:
110
  displayed_text += char
111
+
112
+ if gradient:
113
+ placeholder.markdown(f"""
114
+ <h2 style="
115
+ color: #3D6D6B;
116
+ text-align: left;
117
+ background: linear-gradient(90deg, #3D6D6B, #6EA8A5);
118
+ -webkit-background-clip: text;
119
+ color: white;
120
+ font-weight: bold;
121
+ font-size: 28px;">
122
+ {displayed_text}
123
+ </h2>
124
+ """, unsafe_allow_html=True)
125
+ else:
126
+ placeholder.markdown(displayed_text)
127
+
128
  time.sleep(speed)
129
+
130
+ def custom_navbar():
131
+ """
132
+ Renders a custom navigation bar with a modern design for the Streamlit application.
133
+
134
+ The navigation bar includes:
135
+ - **Logo:** Displays "Yuvabe Care Companion AI" as the app's brand.
136
+ - **Navigation Links:** Provides links to key sections like Home, Admin Portal, Knowledge Base Explorer, and Chatbot.
137
+
138
+ Key Features:
139
+ - Responsive Design: The layout adjusts for different screen sizes using media queries.
140
+ - Enhanced UI: Includes a soft background, subtle shadow, and smooth hover effects for improved aesthetics.
141
+ - Accessibility: Ensures text visibility and clickable elements for better user interaction.
142
+
143
+ Example Usage:
144
+ >>> custom_navbar()
145
+
146
+ """
147
+ st.markdown(
148
+ """
149
+ <style>
150
+ .navbar {
151
+ display: flex;
152
+ justify-content: space-between;
153
+ align-items: center;
154
+ background-color: #FFFFFF;
155
+ padding: 16px 32px;
156
+ width: 100%;
157
+ border-radius: 50px;
158
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
159
+ border-bottom: 3px solid #2E5D5B;
160
+ box-sizing: border-box;
161
+ white-space: nowrap;
162
+ overflow-x: auto;
163
+ }
164
+
165
+ .logo {
166
+ font-family: 'Arial', sans-serif;
167
+ font-size: 28px;
168
+ font-weight: bold;
169
+ color: #1E293B;
170
+ }
171
+
172
+ .nav-links {
173
+ display: flex;
174
+ gap: 32px;
175
+ align-items: center;
176
+ }
177
+
178
+ .nav-link {
179
+ color: #1E293B !important;
180
+ text-decoration: none;
181
+ font-weight: 600;
182
+ font-size: 22px;
183
+ padding: 8px 16px;
184
+ border-radius: 6px;
185
+ transition: background-color 0.3s ease, color 0.3s ease;
186
+ }
187
+
188
+ .nav-link:hover {
189
+ background-color: #2E5D5B;
190
+ color: #FFFFFF !important;
191
+ border-radius: 50px;
192
+ }
193
+
194
+ @media (max-width: 1024px) {
195
+ .navbar {
196
+ flex-direction: column;
197
+ text-align: center;
198
+ padding: 12px 24px;
199
+ }
200
+
201
+ .nav-links {
202
+ flex-direction: column;
203
+ gap: 12px;
204
+ width: 100%;
205
+ }
206
+
207
+ .nav-link {
208
+ width: 100%;
209
+ text-align: center;
210
+ }
211
+ }
212
+ </style>
213
+
214
+ <div class="navbar">
215
+ <div class="logo">Yuvabe Care Companion AI</div>
216
+ <div class="nav-links">
217
+ <a href="/" class="nav-link">Home</a>
218
+ <a href="/Admin_Portal" class="nav-link">Admin Portal</a>
219
+ <a href="/Knowledge_Base_Explorer" class="nav-link">Knowledge Base Explorer</a>
220
+ <a href="/chatbot" class="nav-link">Chat With Us</a>
221
+ </div>
222
+ </div>
223
+ """,
224
+ unsafe_allow_html=True
225
+ )
226
+
227
+ def set_bg_image(file_path, opacity=0.5):
228
+ """
229
+ Sets a background image for the Streamlit application with optional opacity control.
230
+
231
+ This function applies a background image to the entire Streamlit app (`.stApp` container)
232
+ using CSS with a linear gradient overlay. The overlay enhances text readability by adding
233
+ a semi-transparent dark layer over the image.
234
+
235
+ Args:
236
+ file_path (str): The file path of the background image (supports PNG, JPG, etc.).
237
+ opacity (float, optional): The opacity level of the dark overlay.
238
+ Values range from 0 (fully transparent) to 1 (fully opaque).
239
+ Default is 0.5, providing balanced readability and background visibility.
240
+
241
+ Example Usage:
242
+ ```python
243
+ set_bg_image("src/frontend/images/health_care_banner.png", opacity=0.6)
244
+ ```
245
+
246
+ Notes:
247
+ - Ensure the provided `file_path` is accessible and the image is properly encoded in base64 format.
248
+ - For optimal results, use high-resolution images with suitable contrast to enhance readability.
249
+
250
+ """
251
+ encoded_img = img_to_base64(file_path)
252
+ st.markdown(
253
+ f"""
254
+ <style>
255
+ .stApp {{
256
+ background: linear-gradient(rgba(0, 0, 0, {opacity}), rgba(0, 0, 0, {opacity})),
257
+ url("data:image/png;base64,{encoded_img}") center/cover fixed no-repeat;
258
+ min-height: 100vh;
259
+ }}
260
+ </style>
261
+ """,
262
+ unsafe_allow_html=True
263
+ )
264
+
265
+
266
+
267
+
268
+
269
+
270
+
271
+
272
+
273
+
274
+
275
+
276
+
277
+
278
+
279
+
280
+
281
+
282
+
283
+
284
+
285
+
286
  def get_api_response(endpoint:str, prompt: list):
287
  try:
288
  logger.info(f"Sending user prompt to API endpoint: {API_URL}{endpoint}")
 
337
  except Exception as e:
338
  logger.info(f"Failed to add the chat in db {e}")
339
 
340
+ def display_message_box(role, content):
341
+ """
342
+ Displays a styled message box for user or assistant content.
343
+
344
+ Args:
345
+ role (str): The role of the speaker (e.g., 'User' or 'Assistant').
346
+ content (str): The text content to display.
347
+ """
348
+ # Define styles based on role
349
+ background_color = "#E3F2FD" if role.lower() == 'user' else "#E8F5E9"
350
+ border_color = "#1E88E5" if role.lower() == 'user' else "#43A047"
351
+ text_align = "left" if role.lower() == 'user' else "right"
352
+ flex_direction = "row" if role.lower() == 'user' else "row-reverse"
353
+ avatar = "path_to_user_avatar.png" if role.lower() == 'user' else "path_to_assistant_avatar.png"
354
+
355
+ st.markdown(f"""
356
+ <div style="
357
+ display: flex;
358
+ flex-direction: {flex_direction};
359
+ align-items: center;
360
+ margin-bottom: 10px;
361
+ gap: 10px;">
362
+
363
+ <img src="{avatar}" alt="{role} avatar" style="width: 40px; height: 40px; border-radius: 50%;">
364
+
365
+ <div style="
366
+ background-color: {background_color};
367
+ padding: 15px;
368
+ border-left: 5px solid {border_color};
369
+ border-radius: 8px;
370
+ box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.1);
371
+ width: 100%;">
372
+
373
+ <strong style="color: #333; font-size: 16px;">{role}:</strong>
374
+ <div style="margin-top: 5px; color: #555; font-size: 14px;">
375
+ {content}
376
+ </div>
377
+ </div>
378
+ </div>
379
+ """, unsafe_allow_html=True)
380
+
381
  def get_chat_history_from_db(conversation_id: str, retries=3, delay=5):
382
  API_URL = "http://127.0.0.1:8000/chat-history/retrieve"
383
  for attempt in range(retries):
 
408
  first_message_content = chat_history["data"]["messages"][0].get('content', '').strip()
409
  button_text = first_message_content[:20] if first_message_content else "No Content"
410
 
411
+ if st.sidebar.button(f"Show History for {button_text} : {conversation_id}", key=f"show_history_{conversation_id}"):
412
  st.subheader(f"Chat History for Conversation ID: {conversation_id}")
413
 
414
  for message in chat_history["data"]["messages"]:
 
435
  logger.error(f"Error retrieving chat history for {conversation_id}: {e}")
436
  st.error("An unexpected error occurred while retrieving chat history.")
437
 
438
+ def get_bucket_items():
439
+ API_URL = "http://127.0.0.1:8000/chat-history/bucket-items"
440
+ try:
441
+ response = requests.get(API_URL)
442
+ response.raise_for_status()
443
+ return response.json()
444
+ except Exception as e:
445
+ logger.error(f"Failed to get the bucket items {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/frontend/app/pinecone_data_handler.py CHANGED
@@ -1,67 +1,125 @@
1
  import requests
2
- from app import common_functions
3
  import streamlit as st
4
 
5
-
6
  API_BASE_URL = "http://localhost:8000/knowledge-base"
7
 
8
- def upsert_data(st):
9
- st.header("Upsert Data")
 
 
 
 
 
 
 
 
 
10
  with st.form("upsert_form"):
11
- input_text = st.text_area("Input", "What is mental health?")
12
- output_text = st.text_area("Output", "Mental health refers to...")
13
- instruction_text = st.text_input("Instruction", "Focus on general well-being.")
14
- upsert_submit = st.form_submit_button("Upsert Data")
 
 
15
 
16
  if upsert_submit:
17
- payload = {"data": [{"input": input_text, "output": output_text, "instruction": instruction_text}]}
18
- response = requests.post(f"{API_BASE_URL}/upsert-data", json=payload)
19
- st.success(response.json()["message"]) if response.status_code == 200 else st.error(response.json()["detail"])
 
20
 
21
- def delete_records(st):
22
- st.header("Delete Records")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  with st.form("delete_form"):
24
- ids_to_delete = st.text_area("IDs to Delete", "id_123, id_456").split(",")
25
- delete_submit = st.form_submit_button("Delete Records")
 
 
26
 
27
  if delete_submit:
28
- payload = {"ids_to_delete": [id.strip() for id in ids_to_delete]}
29
- response = requests.post(f"{API_BASE_URL}/delete-records", json=payload)
30
- st.success(response.json()["message"]) if response.status_code == 200 else st.error(response.json()["detail"])
31
-
32
- # def render_metadata_fetch_form(st):
33
- # st.header("Fetch Metadata")
34
- # with st.form("fetch_metadata_form"):
35
- # prompt_text = st.text_area("Describe Your Concern", "e.g., I've been feeling anxious lately.")
36
- # n_result = st.number_input("Number of Results", min_value=1, value=3)
37
- # score_threshold = st.number_input("Score Threshold", min_value=0.0, max_value=1.0, value=0.47)
38
- # metadata_submit = st.form_submit_button("Fetch Metadata")
39
-
40
- # if metadata_submit:
41
- # payload = {
42
- # "prompt": prompt_text,
43
- # "n_result": n_result,
44
- # "score_threshold": score_threshold
45
- # }
46
- # response = requests.post(f"{API_BASE_URL}/fetch-metadata", json=payload)
47
- # if response.status_code == 200:
48
- # metadata = response.json().get('metadata', [])
49
- # try:
50
- # if metadata:
51
- # st.subheader("Search Results")
52
- # for index, entry in enumerate(metadata, start=1):
53
- # st.markdown(f"### Result {index}")
54
- # common_fuctions.typewriter_effect(st, f"**Question:** {entry['question']}")
55
- # common_fuctions.typewriter_effect(st, f"**Answer:** {entry['answer']}")
56
- # st.markdown(f"**Score:** {entry['score']}")
57
- # st.markdown(f"**ID:** {entry['id']}")
58
- # st.markdown("---")
59
- # except Exception as e:
60
- # st.info("There is not relevant data to fetch")
61
-
62
- def render_metadata_fetch_form(st):
63
- st.header("Fetch Metadata")
 
 
 
 
 
 
 
64
  with st.form("fetch_metadata_form"):
 
65
  prompt_text = st.text_area(
66
  "Describe Your Concern",
67
  "e.g., I've been feeling anxious lately.",
@@ -81,30 +139,47 @@ def render_metadata_fetch_form(st):
81
  help="Set the minimum relevance score for the results. Higher values ensure more accurate matches."
82
  )
83
 
84
- metadata_submit = st.form_submit_button("Fetch Metadata")
85
 
86
  if metadata_submit:
 
 
 
 
 
87
  payload = {
88
  "prompt": prompt_text.strip(),
89
  "n_result": n_result,
90
  "score_threshold": score_threshold
91
  }
92
 
93
- try:
94
- response = requests.post(f"{API_BASE_URL}/fetch-metadata", json=payload)
95
- response.raise_for_status() # Ensures HTTP errors are caught
96
- metadata = response.json().get('metadata', [])
97
-
98
- if metadata:
99
- st.subheader("Search Results")
100
- for index, entry in enumerate(metadata, start=1):
101
- st.markdown(f"### Result {index}")
102
- common_functions.typewriter_effect(f"**Question:** {entry.get('question', 'N/A')}")
103
- common_functions.typewriter_effect(f"**Answer:** {entry.get('answer', 'N/A')}")
104
- st.markdown(f"**Score:** {entry.get('score', 'N/A')}")
105
- st.markdown(f"**ID:** {entry.get('id', 'N/A')}")
106
- st.markdown("---")
107
- else:
108
- st.info("No relevant data found based on your input. Try refining your concern or adjusting the threshold.")
109
- except Exception as e:
110
- st.error(f"An unexpected error occurred: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import requests
2
+ from frontend.app import common_functions
3
  import streamlit as st
4
 
 
5
  API_BASE_URL = "http://localhost:8000/knowledge-base"
6
 
7
+ def upsert_data():
8
+ """
9
+ Displays a form to upsert data into the Pinecone database.
10
+
11
+ Features:
12
+ - Users can provide 'Input', 'Output', and 'Instruction'.
13
+ - Displays appropriate success or error messages.
14
+ - Improved error handling with detailed feedback.
15
+ """
16
+
17
+ st.subheader("Enter the data to upsert")
18
  with st.form("upsert_form"):
19
+ # Input Fields
20
+ input_text = st.text_area("Input", placeholder="Enter input text here...", height=150)
21
+ output_text = st.text_area("Output", placeholder="Enter output text here...", height=150)
22
+ instruction_text = st.text_input("Instruction", placeholder="Provide guidance for the data...")
23
+
24
+ upsert_submit = st.form_submit_button("πŸš€ Upsert Data")
25
 
26
  if upsert_submit:
27
+ # βœ… Validation Check
28
+ if not input_text.strip() or not output_text.strip() or not instruction_text.strip():
29
+ st.error("❗ All fields are required. Please fill out each section before submitting.")
30
+ return
31
 
32
+ # βœ… Payload Creation
33
+ payload = {
34
+ "data": [
35
+ {
36
+ "input": input_text.strip(),
37
+ "output": output_text.strip(),
38
+ "instruction": instruction_text.strip()
39
+ }
40
+ ]
41
+ }
42
+
43
+ # API Call
44
+ with st.spinner("⏳ Processing your data..."):
45
+ try:
46
+ response = requests.post(f"{API_BASE_URL}/upsert-data", json=payload)
47
+ response_data = response.json()
48
+
49
+ if response.status_code == 200:
50
+ st.success(f"βœ… Data successfully upserted: {response_data.get('message', 'Success')}")
51
+ st.toast("πŸŽ‰ Upsert successful!")
52
+ elif response.status_code == 400:
53
+ st.warning(f"⚠️ Bad Request: {response_data.get('detail', 'Check your input data.')}")
54
+ elif response.status_code == 500:
55
+ st.error("❌ Internal Server Error. Please try again later.")
56
+ else:
57
+ st.error(f"❗ Unexpected error: {response_data.get('detail', 'Unknown issue occurred.')}")
58
+ except requests.exceptions.RequestException as e:
59
+ st.error(f"❌ Network error: {e}")
60
+
61
+ def delete_records():
62
+ """
63
+ Displays a form to delete records from the Pinecone database.
64
+
65
+ Features:
66
+ - Users can input comma-separated IDs for deletion.
67
+ - Includes validation checks for empty or malformed IDs.
68
+ - Enhanced error handling for better user feedback.
69
+ """
70
+ st.subheader("Enter id to delete")
71
  with st.form("delete_form"):
72
+ ids_input = st.text_area("IDs to Delete", placeholder="Enter IDs separated by commas (e.g., id_123, id_456)")
73
+ ids_to_delete = [id.strip() for id in ids_input.split(",") if id.strip()]
74
+
75
+ delete_submit = st.form_submit_button("πŸ—‘οΈ Delete Records")
76
 
77
  if delete_submit:
78
+ # βœ… Validation Check
79
+ if not ids_to_delete:
80
+ st.error("❗ Please provide at least one valid ID.")
81
+ return
82
+
83
+ # πŸ”’ Confirmation Prompt for Safety
84
+ if not st.confirm("Are you sure you want to delete the selected records? This action is irreversible."):
85
+ st.info("❗ Deletion canceled.")
86
+ return
87
+
88
+ # βœ… Payload Creation
89
+ payload = {"ids_to_delete": ids_to_delete}
90
+
91
+ # βœ… API Call with Improved Error Handling
92
+ with st.spinner("⏳ Deleting records..."):
93
+ try:
94
+ response = requests.post(f"{API_BASE_URL}/delete-records", json=payload)
95
+ response_data = response.json()
96
+
97
+ if response.status_code == 200:
98
+ st.success(f"βœ… {response_data.get('message', 'Records successfully deleted.')}")
99
+ st.toast("🎯 Deletion successful!")
100
+ elif response.status_code == 400:
101
+ st.warning(f"⚠️ Bad Request: {response_data.get('detail', 'Check the provided IDs.')}")
102
+ elif response.status_code == 404:
103
+ st.warning("⚠️ No matching records found. Please verify the provided IDs.")
104
+ elif response.status_code == 500:
105
+ st.error("❌ Internal Server Error. Please try again later.")
106
+ else:
107
+ st.error(f"❗ Unexpected error: {response_data.get('detail', 'Unknown issue occurred.')}")
108
+ except requests.exceptions.RequestException as e:
109
+ st.error(f"❌ Network error: {e}")
110
+
111
+ def render_metadata_fetch_form():
112
+ """
113
+ Renders a form to fetch metadata based on user concerns.
114
+
115
+ Features:
116
+ - Input validation to ensure meaningful data is provided.
117
+ - Displays metadata in a visually appealing format.
118
+ - Improved error handling with detailed messages.
119
+ """
120
+ st.header("πŸ“‹ Fetch Metadata")
121
  with st.form("fetch_metadata_form"):
122
+ # πŸ“ Input Fields
123
  prompt_text = st.text_area(
124
  "Describe Your Concern",
125
  "e.g., I've been feeling anxious lately.",
 
139
  help="Set the minimum relevance score for the results. Higher values ensure more accurate matches."
140
  )
141
 
142
+ metadata_submit = st.form_submit_button("πŸ” Fetch Metadata")
143
 
144
  if metadata_submit:
145
+ # βœ… Input Validation
146
+ if not prompt_text.strip():
147
+ st.warning("❗ Please provide a valid concern description.")
148
+ return
149
+
150
  payload = {
151
  "prompt": prompt_text.strip(),
152
  "n_result": n_result,
153
  "score_threshold": score_threshold
154
  }
155
 
156
+ # πŸ”„ Enhanced API Request with Better Error Handling
157
+ with st.spinner("⏳ Fetching metadata..."):
158
+ try:
159
+ response = requests.post(f"{API_BASE_URL}/fetch-metadata", json=payload)
160
+ response.raise_for_status()
161
+ metadata = response.json().get('metadata', [])
162
+
163
+ # βœ… Display Results
164
+ if metadata:
165
+ st.success(f"βœ… Found {len(metadata)} relevant result(s).")
166
+ st.subheader("Search Results")
167
+
168
+ for index, entry in enumerate(metadata, start=1):
169
+ common_functions.typewriter_effect(f"**🧠 Question:** {entry.get('question', 'N/A')}",speed=0)
170
+ common_functions.typewriter_effect(f"**πŸ’¬ Answer:** {entry.get('answer', 'N/A')}",speed=0)
171
+ st.markdown(f"**πŸ“ˆ Score:** `{entry.get('score', 'N/A')}`")
172
+ st.markdown(f"**πŸ†” ID:** `{entry.get('id', 'N/A')}`")
173
+
174
+ else:
175
+ st.info("πŸ€” No relevant data found. Try refining your concern or adjusting the score threshold.")
176
+
177
+ # Exception Handling for Specific Errors
178
+ except requests.exceptions.HTTPError as http_err:
179
+ st.error(f"❌ HTTP Error: {http_err}")
180
+ except requests.exceptions.ConnectionError:
181
+ st.error("❌ Network error. Please check your internet connection.")
182
+ except requests.exceptions.Timeout:
183
+ st.error("❌ Request timed out. Please try again later.")
184
+ except requests.exceptions.RequestException as e:
185
+ st.error(f"❌ Unexpected error: {e}")
src/frontend/home.py CHANGED
@@ -1,84 +1,77 @@
1
  import streamlit as st
2
- from app import common_functions
3
 
4
- # # Page Configuration
 
 
5
  common_functions.config_homepage()
6
  common_functions.set_bg_image("src/frontend/images/health_care_baner.png")
7
  common_functions.custom_navbar()
8
  st.divider()
9
 
10
  def render_homepage():
11
- # Display the animated text
12
- welcome_text = "Welcome to the Yuvabe Care Companion AI!"
13
- container = st.empty()
14
- common_functions.type_text(container, welcome_text)
15
- # Feature Overview Section
16
- text = ("""
17
- Key Features
18
-
19
- - Admin Portal β€” Effortlessly manage records, track data, and configure settings with ease.
20
-
21
- - Knowledge Base Explorer β€” Discover precise and relevant insights using advanced vector search technology.
22
-
23
- - Chat with Us β€” Engage with our intelligent assistant for personalized guidance, helping you articulate your health concerns with clarity and confidence.
24
 
25
- > πŸ’‘ Explore each section to unlock powerful features tailored to enhance your experience.
26
- """)
 
 
 
 
 
 
 
27
 
28
- st.markdown(f"""
29
- <h2 style="
30
- text-align: left;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  font-weight: bold;
32
- font-size: 18px;
33
- color: white;
34
- background-color: #1B3C59;
35
- padding: 10px 20px;
36
- border-radius: 8px;
37
  ">
38
- {text}
39
- </h2>
40
- """, unsafe_allow_html=True)
41
-
42
- render_homepage()
43
-
44
- # def render_homepage():
45
- # """Renders the Yuvabe Care Companion AI homepage."""
46
-
47
- # # Welcome Section with Visual
48
- # st.image("src/frontend/images/health_care_baner.png",
49
- # use_container_width=True,
50
- # caption="Your AI-Powered Health Companion")
51
-
52
- # # Navigation Tabs
53
- # Home, Admin_Portal, Knowledge_Base_Explorer = st.tabs(
54
- # ["🏠 Home", "πŸ”’ Admin Portal", "πŸ“š Knowledge Base Explorer"]
55
- # )
56
-
57
- # with Home:
58
- # st.markdown("""
59
- # ### πŸ‘‹ Welcome to the Yuvabe Care Companion AI!
60
- # This platform offers comprehensive tools to support your healthcare journey. Use the tabs above to navigate:
61
- # """)
62
-
63
- # # Feature Overview Section
64
- # st.markdown("""
65
- # ### πŸ”Ή Key Features
66
- # - **Admin Portal** β€” Manage records, data, and configurations efficiently.
67
- # - **Knowledge Base Explorer** β€” Leverage advanced vector search to find relevant knowledge entries with precision.
68
- # - **Patient Assistance** β€” Personalized guidance to help patients describe their concerns.
69
-
70
- # > πŸ’‘ *Explore each section for detailed functionality.*
71
- # """)
72
-
73
- # with Admin_Portal:
74
- # admin_page.render_admin_portal()
75
- # # if st.button("Go to Admin Portal"):
76
- # # st.switch_page("pages/admin_portal.py")
77
-
78
- # with Knowledge_Base_Explorer:
79
- # knowledge_base_explorer_page.render_knowledge_base_explorer()
80
- # if st.button("Go to Knowledge Base Explorer"):
81
- # st.switch_page("pages/knowledge_base_explorer.py")
82
 
83
- # Render the Homepage
84
- # render_homepage()
 
1
  import streamlit as st
2
+ from frontend.app import common_functions
3
 
4
+ WELCOME_TEXT = "Welcome to the Yuvabe Care Companion AI!"
5
+
6
+ # Page Configuration
7
  common_functions.config_homepage()
8
  common_functions.set_bg_image("src/frontend/images/health_care_baner.png")
9
  common_functions.custom_navbar()
10
  st.divider()
11
 
12
  def render_homepage():
13
+ """
14
+ Renders the Yuvabe Care Companion AI homepage with improved visuals and enhanced user experience.
15
+
16
+ Features:
17
+ - Displays a warm welcome message with animated text.
18
+ - Highlights key features using clean and modern UI design.
19
+ - Encourages user engagement with a prominent 'Get Started' call-to-action.
 
 
 
 
 
 
20
 
21
+ Visual Enhancements:
22
+ - Consistent color theme with improved contrast for readability.
23
+ - Box shadows and rounded corners for a modern touch.
24
+ - Organized content using bullet points, ensuring clarity and focus.
25
+
26
+ """
27
+
28
+ # Welcome Text with Animation
29
+ common_functions.typewriter_effect(WELCOME_TEXT, speed=0.02, gradient=True)
30
 
31
+ # Key Features Section
32
+ st.markdown(
33
+ """
34
+ <div style="
35
+ background-color: #1B3C59;
36
+ color: #FFFFFF;
37
+ padding: 25px;
38
+ border-radius: 15px;
39
+ box-shadow: 0 6px 18px rgba(0, 0, 0, 0.4);
40
+ margin-top: 20px;
41
+ ">
42
+ <h2 style="text-align: left; font-weight: bold;">Key Features</h2>
43
+ <ul style="padding-left: 20px;">
44
+ <li><b>πŸ› οΈ Admin Portal</b> β€” Effortlessly manage records, track data, and configure settings with ease.</li>
45
+ <li><b>πŸ“š Knowledge Base Explorer</b> β€” Discover precise and relevant insights using advanced vector search technology.</li>
46
+ <li><b>πŸ’¬ Chat with Us</b> β€” Engage with our intelligent assistant for personalized guidance.</li>
47
+ </ul>
48
+ <p style="margin-top: 15px; font-style: italic; font-weight: bold;">
49
+ πŸ’‘ Explore each section to unlock powerful features tailored to enhance your experience.
50
+ </p>
51
+ </div>
52
+ """,
53
+ unsafe_allow_html=True
54
+ )
55
+
56
+ # Call-to-Action Section
57
+ st.markdown(
58
+ """
59
+ <div style="
60
+ text-align: center;
61
+ margin-top: 30px;
62
+ padding: 18px 35px;
63
+ background-color: #4CAF50;
64
+ color: #FFFFFF;
65
  font-weight: bold;
66
+ font-size: 20px;
67
+ border-radius: 12px;
68
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
 
 
69
  ">
70
+ 🌿 Ready to Get Started? Begin Your Journey Now! πŸš€
71
+ </div>
72
+ """,
73
+ unsafe_allow_html=True
74
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
 
76
+ if __name__ == "__main__":
77
+ render_homepage()
src/frontend/pages/Admin_Portal.py CHANGED
@@ -1,49 +1,98 @@
1
  import streamlit as st
2
- from app import pinecone_data_handler
3
- from app import common_functions
4
 
5
  # # Page Configuration
6
  common_functions.config_homepage()
 
7
 
8
  def render_admin_portal():
9
- """Renders the enhanced Admin Portal page with improved UI and navigation."""
10
-
11
- # Header Section
12
- st.markdown("<h1 class='header-text'>πŸ› οΈ Admin Portal</h1>", unsafe_allow_html=True)
13
- st.markdown("""
14
- Welcome to the **Admin Portal**.
15
- Manage your Pinecone database with secure and efficient tools.
16
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  st.divider()
18
 
19
- # Data Manager Tabs
20
  DataManager = st.tabs(["πŸ“‚ Pinecone Data Manager"])[0]
21
 
22
  with DataManager:
23
- Upsert, Delete = st.tabs(["Upsert Data", "Delete Records"])
24
 
25
  # Upsert Section
26
  with Upsert:
27
- st.markdown("<div class='card'>", unsafe_allow_html=True)
28
- st.markdown("### πŸ“₯ Upsert Data")
29
- st.info(
30
- "Use this section to **insert** or **update** records in Pinecone."
31
- "\n\nβœ… Ensure your data is correctly formatted before uploading."
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  )
33
- st.markdown("---")
34
- pinecone_data_handler.upsert_data(st)
35
- st.markdown("</div>", unsafe_allow_html=True)
 
 
36
 
37
  # Delete Section
38
  with Delete:
39
- st.markdown("<div class='card'>", unsafe_allow_html=True)
40
- st.markdown("### ⚠️ Delete Records")
41
- st.error(
42
- "❗ **Warning:** Deleting data is irreversible.\n"
43
- "Proceed with caution."
 
 
 
 
 
 
 
 
 
 
 
44
  )
45
- # Confirmation Dialog for Safety
46
- pinecone_data_handler.delete_records(st)
 
47
 
48
  # Call the function to render the Admin Portal
49
  if __name__ == "__main__":
 
1
  import streamlit as st
2
+ from frontend.app import pinecone_data_handler,common_functions
 
3
 
4
  # # Page Configuration
5
  common_functions.config_homepage()
6
+ # common_functions.set_bg_image("src/frontend/images/health_care_baner.png")
7
 
8
  def render_admin_portal():
9
+
10
+ """
11
+ Renders the enhanced Admin Portal page with improved UI, navigation, and user guidance.
12
+
13
+ Features:
14
+ - Upsert data functionality with informative tips.
15
+ - Delete records feature with enhanced warnings and confirmation prompts.
16
+ """
17
+
18
+ # Header Section
19
+ st.markdown(
20
+ """
21
+ <div style="
22
+ background-color: #1B3C59;
23
+ color: #FFFFFF;
24
+ padding: 10px;
25
+ border-radius: 12px;
26
+ text-align: center;
27
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
28
+ border-radius: 80px;
29
+ ">
30
+ <h1>πŸ› οΈ Admin Portal</h1>
31
+ <p style="font-size: 16px;">
32
+ Manage your Pinecone database securely and efficiently.
33
+ </p>
34
+ </div>
35
+ """,
36
+ unsafe_allow_html=True
37
+ )
38
+
39
  st.divider()
40
 
41
+ # Data Manager Tabs
42
  DataManager = st.tabs(["πŸ“‚ Pinecone Data Manager"])[0]
43
 
44
  with DataManager:
45
+ Upsert, Delete = st.tabs(["🟒 Upsert Data", "πŸ”΄ Delete Records"])
46
 
47
  # Upsert Section
48
  with Upsert:
49
+ st.markdown(
50
+ """
51
+ <div style="
52
+ background-color: #E3F2FD;
53
+ padding: 20px;
54
+ border-radius: 10px;
55
+ box-shadow: 0 3px 8px rgba(0, 0, 0, 0.15);
56
+ ">
57
+ <h3>πŸ“₯ Upsert Data</h3>
58
+ <p style="color: #1976D2;">
59
+ Use this section to <b>insert</b> or <b>update</b> records in Pinecone.
60
+ </p>
61
+ <p>
62
+ βœ… Ensure your data is correctly formatted before uploading.<br>
63
+ </p>
64
+ </div>
65
+ """,
66
+ unsafe_allow_html=True
67
  )
68
+
69
+ st.divider()
70
+
71
+ # Call Upsert Function
72
+ pinecone_data_handler.upsert_data()
73
 
74
  # Delete Section
75
  with Delete:
76
+ st.markdown(
77
+ """
78
+ <div style="
79
+ background-color: #FFEBEE;
80
+ padding: 20px;
81
+ border-radius: 10px;
82
+ box-shadow: 0 3px 8px rgba(0, 0, 0, 0.15);
83
+ ">
84
+ <h3>⚠️ Delete Records</h3>
85
+ <p style="color: #D32F2F;">
86
+ ❗ <b>Warning:</b> Deleting data is irreversible.<br>
87
+ Please confirm your action before proceeding.
88
+ </p>
89
+ </div>
90
+ """,
91
+ unsafe_allow_html=True
92
  )
93
+
94
+ st.divider()
95
+ pinecone_data_handler.delete_records()
96
 
97
  # Call the function to render the Admin Portal
98
  if __name__ == "__main__":
src/frontend/pages/{chatbot.py β†’ Chat_With_Us.py} RENAMED
@@ -1,13 +1,13 @@
1
  import streamlit as st
2
  import requests
3
- from app import common_functions
4
  from datetime import datetime
5
 
6
  API_URL = "http://localhost:8000/chat/get-health-advice/"
7
  NUMBER_OF_MESSAGES_TO_DISPLAY = 20
8
  common_functions.config_homepage()
9
  common_functions.set_page_title()
10
- common_functions.set_bg_image("src/frontend/images/health_care_baner_2.jpg")
11
  # Initialize conversation history
12
  def initialize_conversation():
13
  assistant_message = ("Hello! I am your Yuvabe Care Companion AI, here to assist you with general medicine queries. "
@@ -36,14 +36,18 @@ def render_chatbot():
36
  if 'conversation_id' not in st.session_state:
37
  st.session_state.conversation_id = datetime.now().strftime("%Y-%m-%d")
38
 
39
- common_functions.display_chat_history(st.session_state.conversation_id)
 
 
 
40
 
41
  # Display chat history
42
  for message in st.session_state.conversation_history [-NUMBER_OF_MESSAGES_TO_DISPLAY:]:
43
  role = message["role"]
44
  avatar_image = "src/frontend/images/chat_doctor_logo.png" if role == "assistant" else "src/frontend/images/healthy.png" if role == "user" else None
45
  with st.chat_message(role, avatar=avatar_image):
46
- st.write(message["content"])
 
47
 
48
  # User Input
49
  user_input = st.chat_input("Ask your health-related question:")
 
1
  import streamlit as st
2
  import requests
3
+ from frontend.app import common_functions
4
  from datetime import datetime
5
 
6
  API_URL = "http://localhost:8000/chat/get-health-advice/"
7
  NUMBER_OF_MESSAGES_TO_DISPLAY = 20
8
  common_functions.config_homepage()
9
  common_functions.set_page_title()
10
+ # common_functions.set_bg_image("src/frontend/images/health_care_baner_2.jpg")
11
  # Initialize conversation history
12
  def initialize_conversation():
13
  assistant_message = ("Hello! I am your Yuvabe Care Companion AI, here to assist you with general medicine queries. "
 
36
  if 'conversation_id' not in st.session_state:
37
  st.session_state.conversation_id = datetime.now().strftime("%Y-%m-%d")
38
 
39
+ conversation_ids = common_functions.get_bucket_items()
40
+ if conversation_ids:
41
+ for conversation_id in conversation_ids[-3:]:
42
+ common_functions.display_chat_history(conversation_id)
43
 
44
  # Display chat history
45
  for message in st.session_state.conversation_history [-NUMBER_OF_MESSAGES_TO_DISPLAY:]:
46
  role = message["role"]
47
  avatar_image = "src/frontend/images/chat_doctor_logo.png" if role == "assistant" else "src/frontend/images/healthy.png" if role == "user" else None
48
  with st.chat_message(role, avatar=avatar_image):
49
+ common_functions.display_message_box(role,message['content'])
50
+ # st.write(message["content"])
51
 
52
  # User Input
53
  user_input = st.chat_input("Ask your health-related question:")
src/frontend/pages/Knowledge_Base_Explorer.py CHANGED
@@ -1,22 +1,65 @@
1
  import streamlit as st
2
- from app import pinecone_data_handler, common_functions
3
 
 
4
  common_functions.config_homepage()
5
 
6
  def render_knowledge_base_explorer():
7
- """Renders the Knowledge Base Explorer page with improved UI and navigation."""
8
-
9
- # Header Section
10
- st.title("πŸ“š Knowledge Base Explorer")
11
- st.markdown("""
12
- ### Discover Helpful Information!
13
- Enter your concerns below to receive insights and solutions tailored to your needs.
14
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
- # Knowledge Base Section
17
- with st.expander("πŸ” Explore the Knowledge Base"):
18
- pinecone_data_handler.render_metadata_fetch_form(st)
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  # Call the function to render the Knowledge Base Explorer
21
  if __name__ == "__main__":
22
  render_knowledge_base_explorer()
 
1
  import streamlit as st
2
+ from frontend.app import pinecone_data_handler, common_functions
3
 
4
+ # Page Configuration
5
  common_functions.config_homepage()
6
 
7
  def render_knowledge_base_explorer():
8
+ """Renders the Knowledge Base Explorer page for fetching accurate metadata from Pinecone Vector DB."""
9
+
10
+ st.markdown(
11
+ """
12
+ <div style="
13
+ background-color: #1B3C59;
14
+ color: #FFFFFF;
15
+ padding: 20px;
16
+ border-radius: 12px;
17
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
18
+ text-align: center;
19
+ ">
20
+ <h1>πŸ“š Knowledge Base Explorer</h1>
21
+ <p>Powered by <b>Pinecone Vector DB</b> for precise metadata retrieval.</p>
22
+ </div>
23
+ """,
24
+ unsafe_allow_html=True
25
+ )
26
+
27
+ st.divider()
28
+
29
+ # Guidance Section
30
+ st.markdown(
31
+ """
32
+ ### How to Use the Knowledge Base Explorer
33
+ 1. **Enter your query** related to health concerns.
34
+ 2. Click **Fetch Metadata** to retrieve the most relevant insights.
35
+ 3. Results are fetched from **Pinecone Vector DB**, ensuring fast and accurate responses.
36
 
37
+ βœ… **Pro Tip:** Use precise keywords for better results (e.g., "mental health tips" instead of "help").
38
+ """
39
+ )
40
 
41
+ st.divider()
42
+
43
+ # Knowledge Base Section
44
+ with st.expander("πŸ” **Explore the Knowledge Base (Pinecone Vector DB)**", expanded=True):
45
+ st.info(
46
+ "πŸ’‘ **Looking for specific metadata?**"
47
+ "\nOur system intelligently maps your query to the most relevant results."
48
+ )
49
+
50
+ try:
51
+ result = pinecone_data_handler.render_metadata_fetch_form()
52
+
53
+ # if result:
54
+ # st.success("βœ… **Metadata fetched successfully!**")
55
+ # st.write(result)
56
+ # else:
57
+ # st.warning("⚠️ No relevant metadata found. Try refining your query for better results.")
58
+
59
+ except Exception as e:
60
+ st.error(f"❌ An error occurred while fetching metadata: {str(e)}")
61
+
62
+
63
  # Call the function to render the Knowledge Base Explorer
64
  if __name__ == "__main__":
65
  render_knowledge_base_explorer()