Sebunya commited on
Commit
2d2f030
·
verified ·
1 Parent(s): 4b4b301

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +45 -26
app.py CHANGED
@@ -8,10 +8,13 @@ import google.generativeai as genai
8
  import chromadb
9
  from langchain_chroma import Chroma
10
 
11
- # Load Gemini API key from environment variable
12
  genai.configure(api_key=os.environ["GEMINI_API_KEY"])
 
 
 
13
 
14
- # Load and clean knowledge base
15
  df_kb = pd.read_json("XENO_Uganda_KnowledgeBase_Advisory.json")
16
  df_kb.dropna(subset=['Content'], inplace=True)
17
 
@@ -33,10 +36,8 @@ def prepare_documents(data):
33
  xeno_data_list = df_kb.to_dict('records')
34
  documents, metadatas, ids = prepare_documents(xeno_data_list)
35
 
36
- # ChromaDB setup
37
  client = chromadb.PersistentClient(path="./xeno_db")
38
- collection_name = "xeno_collection"
39
-
40
  try:
41
  collection = client.get_collection(name=collection_name)
42
  except:
@@ -46,27 +47,44 @@ except:
46
  vector_store = Chroma(client=client, collection_name=collection_name)
47
  retriever = vector_store.as_retriever(search_type="similarity", search_kwargs={"k": 4})
48
 
49
- embedding_model = "models/embedding-001"
50
- llm_model_name = "models/gemma-3-4b-it"
51
-
52
- SYSTEM_PROMPT = """
53
- You are XENO Support Assistant, an AI-powered helpful and professional customer service representative.
54
  Use only the information provided in the knowledge base context to answer user queries.
55
  Do not hallucinate. If context doesn't contain relevant info, say so in a calm polite manner.
56
-
57
- """
58
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  def generate_xeno_response(context, question):
60
  model = genai.GenerativeModel(llm_model_name)
61
- user_prompt = f"""{SYSTEM_PROMPT}
62
- ### CONTEXT ###
63
- {context}
64
- ### QUESTION ###
65
- {question}"""
66
- response = model.generate_content(user_prompt)
 
 
67
  return response.text.strip()
68
 
 
69
  def get_context_and_answer(message, history):
 
 
 
70
  queried_results = retriever.invoke(message)
71
  query_embedding = genai.embed_content(model=embedding_model,
72
  content=message,
@@ -78,13 +96,15 @@ def get_context_and_answer(message, history):
78
  task_type="retrieval_document")['embedding']
79
  cos_sim = util.cos_sim(torch.tensor(query_embedding).float(), torch.tensor(doc_embedding).float())[0][0].item()
80
  cosine_scores.append(cos_sim)
81
- context = ""
82
- top_docs = sorted(zip(queried_results, cosine_scores), key=lambda x: x[1], reverse=True)[:2]
83
- for i, (result, score) in enumerate(top_docs, 1):
84
- context += f"Knowledge Entry {i}:\nQ: {result.metadata['question']}\nA: {result.metadata['content']}\n{'-'*40}\n"
85
- return generate_xeno_response(context, message)
86
 
 
 
 
 
 
 
87
 
 
88
  iface = gr.ChatInterface(
89
  fn=get_context_and_answer,
90
  title="ASKXENO",
@@ -93,5 +113,4 @@ iface = gr.ChatInterface(
93
  )
94
 
95
  if __name__ == "__main__":
96
- iface.launch(share=True)
97
-
 
8
  import chromadb
9
  from langchain_chroma import Chroma
10
 
11
+ # === Configuration ===
12
  genai.configure(api_key=os.environ["GEMINI_API_KEY"])
13
+ embedding_model = "models/embedding-001"
14
+ llm_model_name = "models/gemma-3-4b-it"
15
+ collection_name = "xeno_collection"
16
 
17
+ # === Load and Clean Knowledge Base ===
18
  df_kb = pd.read_json("XENO_Uganda_KnowledgeBase_Advisory.json")
19
  df_kb.dropna(subset=['Content'], inplace=True)
20
 
 
36
  xeno_data_list = df_kb.to_dict('records')
37
  documents, metadatas, ids = prepare_documents(xeno_data_list)
38
 
39
+ # === Setup ChromaDB ===
40
  client = chromadb.PersistentClient(path="./xeno_db")
 
 
41
  try:
42
  collection = client.get_collection(name=collection_name)
43
  except:
 
47
  vector_store = Chroma(client=client, collection_name=collection_name)
48
  retriever = vector_store.as_retriever(search_type="similarity", search_kwargs={"k": 4})
49
 
50
+ # === Prompt System ===
51
+ SYSTEM_PROMPT = """You are XENO Support Assistant, an AI-powered helpful and professional customer service representative.
 
 
 
52
  Use only the information provided in the knowledge base context to answer user queries.
53
  Do not hallucinate. If context doesn't contain relevant info, say so in a calm polite manner.
54
+ Only use context that is clearly relevant to the user's question.
55
+ For greetings like “hi” or “hello”, respond politely without using the context."""
56
+
57
+ # === Context Processing ===
58
+ def process_context(results, cosine_scores, max_results=2):
59
+ sorted_indices = np.argsort(cosine_scores)[::-1][:max_results]
60
+ formatted_context = ""
61
+ for i, idx in enumerate(sorted_indices, 1):
62
+ result = results[idx]
63
+ score = cosine_scores[idx]
64
+ formatted_context += f"Knowledge Entry {i}:\n"
65
+ formatted_context += f"Q: {result.metadata.get('question', 'N/A')}\n"
66
+ formatted_context += f"A: {result.metadata.get('content', 'N/A')}\n"
67
+ formatted_context += "-" * 40 + "\n"
68
+ return formatted_context
69
+
70
+ # === LLM Generation ===
71
  def generate_xeno_response(context, question):
72
  model = genai.GenerativeModel(llm_model_name)
73
+ prompt = f"""{SYSTEM_PROMPT}
74
+
75
+ ### CONTEXT ###
76
+ {context}
77
+
78
+ ### QUESTION ###
79
+ {question}"""
80
+ response = model.generate_content(prompt)
81
  return response.text.strip()
82
 
83
+ # === Main Interface Logic ===
84
  def get_context_and_answer(message, history):
85
+ if message.lower().strip() in {"hi", "hello", "hey"}:
86
+ return "Hello! How can I assist you with XENO services today?"
87
+
88
  queried_results = retriever.invoke(message)
89
  query_embedding = genai.embed_content(model=embedding_model,
90
  content=message,
 
96
  task_type="retrieval_document")['embedding']
97
  cos_sim = util.cos_sim(torch.tensor(query_embedding).float(), torch.tensor(doc_embedding).float())[0][0].item()
98
  cosine_scores.append(cos_sim)
 
 
 
 
 
99
 
100
+ # If none of the results have sufficient similarity, fallback
101
+ if max(cosine_scores) < 0.4:
102
+ return "I'm sorry, I couldn't find the specific information you're looking for in my knowledge base."
103
+
104
+ context = process_context(queried_results, cosine_scores)
105
+ return generate_xeno_response(context, message)
106
 
107
+ # === Gradio UI ===
108
  iface = gr.ChatInterface(
109
  fn=get_context_and_answer,
110
  title="ASKXENO",
 
113
  )
114
 
115
  if __name__ == "__main__":
116
+ iface.launch()