duatanzeel commited on
Commit
1871256
Β·
verified Β·
1 Parent(s): 7bef9c4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +45 -99
app.py CHANGED
@@ -7,151 +7,97 @@ import gradio as gr
7
  from dotenv import load_dotenv
8
  import os
9
 
10
- load_dotenv()
 
 
 
 
 
 
 
 
11
 
12
- # ==========================
13
- # Globals
14
- # ==========================
15
- MODEL_NAME = "gemini-2.5-flash"
16
  embedder = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
17
 
18
- index = None
19
- meta = None
20
- client = None
21
 
 
 
 
22
 
23
- # ==========================
24
- # Helper Functions
25
- # ==========================
26
  def chunk_text(text, chunk_chars=800, overlap=100):
27
- """Split text into overlapping chunks"""
28
  chunks, start = [], 0
29
  while start < len(text):
30
  end = min(start + chunk_chars, len(text))
31
  chunks.append(text[start:end].strip())
32
  start = end - overlap
33
- if start < 0:
34
- start = 0
35
- if end == len(text):
36
- break
37
  return [c for c in chunks if c]
38
 
 
 
39
 
40
- def build_index(file_obj):
41
- """Build FAISS index from uploaded file"""
42
- global index, meta
43
-
44
- raw_text = file_obj.read().decode("utf-8")
45
- chunks = chunk_text(raw_text)
46
-
47
- embeddings = embedder.encode(
48
- chunks, convert_to_numpy=True, normalize_embeddings=True
49
- )
50
-
51
- dim = embeddings.shape[1]
52
- index = faiss.IndexFlatIP(dim)
53
- index.add(embeddings)
54
- meta = [{"id": i, "chunk": c} for i, c in enumerate(chunks)]
55
-
56
- return "βœ… File processed! You can now ask questions."
57
-
58
 
59
- def set_api_key(api_key):
60
- """Initialize Gemini client with API key"""
61
- global client
62
- try:
63
- client = genai.Client(api_key=api_key)
64
- return "βœ… API Key set successfully!"
65
- except Exception as e:
66
- return f"❌ Error setting API Key: {e}"
67
 
 
 
 
68
 
 
69
  def retrieve(query, top_k=3):
70
- """Retrieve top matching chunks"""
71
- if index is None:
72
- return []
73
-
74
  q_emb = embedder.encode([query], convert_to_numpy=True, normalize_embeddings=True)
75
  scores, idxs = index.search(q_emb, top_k)
76
-
77
  results = []
78
  for i in idxs[0]:
79
- if i == -1:
80
- continue
81
  results.append(meta[i]["chunk"])
82
  return results
83
 
84
-
85
  def call_gemini(system_prompt, user_prompt):
86
- """Query Gemini API"""
87
- if client is None:
88
- return "❌ Please enter your Gemini API Key first."
89
-
90
  try:
91
  response = client.models.generate_content(
92
  model=MODEL_NAME,
93
  contents=f"{system_prompt}\n\n{user_prompt}",
94
  config=types.GenerateContentConfig(
95
- thinking_config=types.ThinkingConfig(thinking_budget=0)
96
  ),
97
  )
98
  return response.text
99
  except Exception as e:
100
  return f"❌ Gemini error: {e}"
101
 
102
-
103
  def answer_question(question, top_k=3):
104
- """Answer user query based on retrieved context"""
105
  context_chunks = retrieve(question, top_k)
106
  if not context_chunks:
107
- return "⚠️ No relevant context found in your file."
108
-
109
  context = "\n---\n".join(context_chunks)
110
- system_prompt = """You are a professional Arduino freelancer.
111
- Answer ONLY using the provided Fiverr chat context.
112
- If the answer is not in the context, reply:
113
- "I don’t know based on the provided chat."
114
- """
115
- user_prompt = f"""Client asked:
116
- {question}
117
-
118
- Relevant chat context:
119
- {context}
120
- """
121
- return call_gemini(system_prompt, user_prompt)
122
-
123
 
 
124
  def chatbot_fn(message, history):
125
- """Gradio chatbot function"""
126
  reply = answer_question(message)
127
  return reply
128
 
129
-
130
- # ==========================
131
- # Gradio UI
132
- # ==========================
133
  with gr.Blocks() as demo:
134
  gr.Markdown("## πŸ€– Arduino Fiverr Chatbot (Gemini Powered)")
 
135
 
136
- with gr.Row():
137
- api_key_box = gr.Textbox(label="πŸ”‘ Enter Gemini API Key", type="password")
138
- api_key_btn = gr.Button("Set API Key")
139
- api_status = gr.Label(label="API Key Status")
140
-
141
- api_key_btn.click(set_api_key, inputs=api_key_box, outputs=api_status)
142
-
143
- with gr.Row():
144
- file_upload = gr.File(label="πŸ“‚ Upload your Fiverr chat (.txt)", type="file")
145
- file_status = gr.Label(label="File Status")
146
-
147
- file_upload.upload(build_index, inputs=file_upload, outputs=file_status)
148
-
149
- gr.ChatInterface(
150
- fn=chatbot_fn,
151
- title="Arduino Client Assistant",
152
- textbox="Ask your client-related question here...",
153
- )
154
-
155
- # Run app
156
- if __name__ == "__main__":
157
- demo.launch()
 
7
  from dotenv import load_dotenv
8
  import os
9
 
10
+ import faiss
11
+ import gradio as gr
12
+ from sentence_transformers import SentenceTransformer
13
+ from google import genai
14
+ from google.genai import types
15
+
16
+ # βœ… Take Gemini API key from user
17
+ api_key = input("πŸ”‘ Enter your Gemini API Key: ")
18
+ client = genai.Client(api_key=api_key)
19
 
20
+ # βœ… Load embedding model
 
 
 
21
  embedder = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
22
 
23
+ MODEL_NAME = "gemini-2.5-flash" # use stable model
 
 
24
 
25
+ # βœ… Read file (assumes filename already set from upload)
26
+ with open(filename, "r", encoding="utf-8") as f:
27
+ raw_text = f.read()
28
 
29
+ # βœ… Split into chunks
 
 
30
  def chunk_text(text, chunk_chars=800, overlap=100):
 
31
  chunks, start = [], 0
32
  while start < len(text):
33
  end = min(start + chunk_chars, len(text))
34
  chunks.append(text[start:end].strip())
35
  start = end - overlap
36
+ if start < 0: start = 0
37
+ if end == len(text): break
 
 
38
  return [c for c in chunks if c]
39
 
40
+ chunks = chunk_text(raw_text)
41
+ embeddings = embedder.encode(chunks, convert_to_numpy=True, normalize_embeddings=True)
42
 
43
+ dim = embeddings.shape[1]
44
+ index = faiss.IndexFlatIP(dim)
45
+ index.add(embeddings)
46
+ meta = [{"id": i, "chunk": c} for i, c in enumerate(chunks)]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
+ # βœ… Prompt templates
49
+ SYSTEM_TEMPLATE = """You are a professional Arduino freelancer.
50
+ Answer ONLY using the provided Fiverr chat context.
51
+ If the answer is not in the context, reply:
52
+ "I don’t know based on the provided chat."
53
+ """
54
+ USER_TEMPLATE = """Client asked:
55
+ {question}
56
 
57
+ Relevant chat context:
58
+ {context}
59
+ """
60
 
61
+ # βœ… Retrieve top chunks
62
  def retrieve(query, top_k=3):
 
 
 
 
63
  q_emb = embedder.encode([query], convert_to_numpy=True, normalize_embeddings=True)
64
  scores, idxs = index.search(q_emb, top_k)
 
65
  results = []
66
  for i in idxs[0]:
67
+ if i == -1: continue
 
68
  results.append(meta[i]["chunk"])
69
  return results
70
 
71
+ # βœ… Call Gemini (new client API)
72
  def call_gemini(system_prompt, user_prompt):
 
 
 
 
73
  try:
74
  response = client.models.generate_content(
75
  model=MODEL_NAME,
76
  contents=f"{system_prompt}\n\n{user_prompt}",
77
  config=types.GenerateContentConfig(
78
+ thinking_config=types.ThinkingConfig(thinking_budget=0) # disables thinking
79
  ),
80
  )
81
  return response.text
82
  except Exception as e:
83
  return f"❌ Gemini error: {e}"
84
 
85
+ # βœ… Answer function
86
  def answer_question(question, top_k=3):
 
87
  context_chunks = retrieve(question, top_k)
88
  if not context_chunks:
89
+ return "⚠️ No relevant context found in your chat file."
 
90
  context = "\n---\n".join(context_chunks)
91
+ user_prompt = USER_TEMPLATE.format(question=question, context=context)
92
+ return call_gemini(SYSTEM_TEMPLATE, user_prompt)
 
 
 
 
 
 
 
 
 
 
 
93
 
94
+ # βœ… Gradio Chatbot
95
  def chatbot_fn(message, history):
 
96
  reply = answer_question(message)
97
  return reply
98
 
 
 
 
 
99
  with gr.Blocks() as demo:
100
  gr.Markdown("## πŸ€– Arduino Fiverr Chatbot (Gemini Powered)")
101
+ gr.ChatInterface(fn=chatbot_fn, title="Arduino Client Assistant")
102
 
103
+ demo.launch()