Darsh1234Tayal commited on
Commit
ade08c2
Β·
verified Β·
1 Parent(s): 1737054

Upload folder using huggingface_hub

Browse files
.ipynb_checkpoints/demo project-checkpoint.py ADDED
@@ -0,0 +1,343 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from langchain_groq import ChatGroq
3
+ import os
4
+ from langgraph.graph import StateGraph, START, END
5
+ from langchain_text_splitters import RecursiveCharacterTextSplitter
6
+ from langchain_chroma import Chroma
7
+ from typing import Annotated
8
+ from typing_extensions import TypedDict
9
+ from pydantic import BaseModel, Field
10
+ from langchain_core.messages import HumanMessage
11
+ import time
12
+ import os
13
+ from langchain_community.document_loaders import PyPDFLoader
14
+ from langchain_huggingface import HuggingFaceEmbeddings
15
+
16
+ os.environ['GROQ_API_KEY'] = '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'
17
+
18
+ class State(TypedDict):
19
+ query: str
20
+ is_safe: bool
21
+ is_relevant: bool
22
+ company_description: str
23
+ answer: str
24
+ vectorstoredb: Chroma
25
+
26
+ class checker_class(BaseModel):
27
+ is_relevant: bool = Field(description="Check whether the given query is relevant to the company.")
28
+
29
+ def invoke_llm(query):
30
+ llm = ChatGroq(model='llama-3.3-70b-versatile')
31
+ try:
32
+ res = llm.invoke(query)
33
+ except:
34
+ time.sleep(60)
35
+ res = llm.invoke(query)
36
+ return res.content
37
+
38
+ def invoke_relevance_checker_llm(query):
39
+ llm = ChatGroq(model='gemma2-9b-it')
40
+ checker_llm = llm.with_structured_output(checker_class)
41
+ try:
42
+ res = checker_llm.invoke([HumanMessage(content=query)])
43
+ except:
44
+ time.sleep(60)
45
+ res = checker_llm.invoke([HumanMessage(content=query)])
46
+ return res.is_relevant
47
+
48
+ def safety_checker(state:State):
49
+ llm = ChatGroq(model='meta-llama/llama-guard-4-12b')
50
+ query = state['query']
51
+ res = llm.invoke(query)
52
+ if res.content == 'safe':
53
+ return {'is_safe':True}
54
+ else:
55
+ return {'is_safe':False, 'answer':"<SAFETY CHECKER> That prompt was harmful, please try something else"}
56
+
57
+ def relevance_checker(state:State):
58
+ prompt = "You are a lenient relevance-checking assistant. You will be given a user query and a company description. Your job is to decide whether the query is relevant to the company.\nβœ… Approve most queries that are even loosely related.\n🚫 Only reject queries that are **clearly unrelated** or have **no connection at all**.\n\n"
59
+ prompt += f"\nQuery: {state['query']}"
60
+ prompt += f"\nDescription: {state['company_description']}"
61
+ res = invoke_relevance_checker_llm(prompt)
62
+ return {'is_relevant':res, 'answer':"Sorry! That doesn't seem to be relevant to us, please try something else."}
63
+
64
+ def agent(state:State):
65
+ relevant_text = ""
66
+ search_docs = state['vectorstoredb'].similarity_search(state['query'])
67
+ for chunk in search_docs:
68
+ relevant_text += f"\n{chunk.page_content}"
69
+ prompt = f"You have to answer this query: {state['query']} based only on the following information: {relevant_text}. Reply only with the answer."
70
+ try:
71
+ res = invoke_llm(prompt)
72
+ except:
73
+ time.sleep(60)
74
+ res = invoke_llm(prompt)
75
+ finally:
76
+ return {'answer':res}
77
+
78
+ def safety_assigner(state:State):
79
+ if state['is_safe']:
80
+ return 'relevant'
81
+ else:
82
+ return 'END'
83
+
84
+ def relevant_assigner(state:State):
85
+ if state['is_relevant']:
86
+ return 'Agent'
87
+ else:
88
+ return 'END'
89
+
90
+ def chat(query, vect, dec):
91
+ yield gr.update(visible=True), ""
92
+ mess = {'query':query, 'vectorstoredb': vect, 'company_description': dec}
93
+ res = graph.invoke(mess)
94
+ yield gr.update(visible=False), res['answer']
95
+
96
+ def setter(pdf_file, description, company_name):
97
+ yield gr.update(visible=False), gr.update(visible=True), gr.update(visible=False), gr.update(visible=False), "", "", ""
98
+ loader = PyPDFLoader(pdf_file)
99
+ docs = loader.load()
100
+ consise_pdf = docs[1].page_content if len(docs) > 1 else docs[0].page_content
101
+ consise_pdf = consise_pdf[:5555]
102
+ full_pdf = ""
103
+ for content in docs:
104
+ full_pdf += f"\n{content.page_content}"
105
+ embeddings = HuggingFaceEmbeddings(model_name='sentence-transformers/all-mpnet-base-v2')
106
+ splitter = RecursiveCharacterTextSplitter(chunk_size=400, chunk_overlap=100)
107
+ chunks = splitter.split_text(full_pdf)
108
+ vector_db = Chroma.from_texts(chunks, embeddings)
109
+ prompt = "You are a company description generator assistant. "
110
+ prompt += "You will be given the name of a company, a short description provided by the owner, "
111
+ prompt += "and additional content extracted from a company file (such as a brochure or document). "
112
+ prompt += "Using this information, generate a concise and professional 3–4 line description of the company. Also, reply in markdown\n\n"
113
+ prompt += f"Company Name: {company_name}\n"
114
+ prompt += f"Owner's Description: {description}\n"
115
+ prompt += f"File Content: {consise_pdf}\n"
116
+ prompt += "Final Description:"
117
+ response = invoke_llm(prompt)
118
+ yield gr.update(visible=False), gr.update(visible=False), gr.update(visible=True), gr.update(visible=False), response, response, vector_db
119
+
120
+ builder = StateGraph(State)
121
+
122
+ builder.add_node("Safety Checker", safety_checker)
123
+ builder.add_node("Relevance Checker", relevance_checker)
124
+ builder.add_node("Agent", agent)
125
+
126
+ builder.add_edge(START, "Safety Checker")
127
+ builder.add_conditional_edges("Safety Checker", safety_assigner, {'relevant':"Relevance Checker", 'END': END})
128
+ builder.add_conditional_edges("Relevance Checker", relevant_assigner, {'Agent':"Agent", 'END':END})
129
+ builder.add_edge("Agent",END)
130
+
131
+ graph = builder.compile()
132
+
133
+ with gr.Blocks(css=".section {margin-bottom: 20px;}") as ui:
134
+
135
+ vectorstore_db = gr.State()
136
+ company_generated_description = gr.State()
137
+
138
+ # πŸŒ€ CSS + HTML animation injection
139
+ header = gr.HTML("""
140
+ <style>
141
+ .fade-in {
142
+ animation: fadeIn 1.2s ease-in;
143
+ }
144
+ .slide-up {
145
+ animation: slideUp 0.8s ease-out;
146
+ }
147
+ @keyframes fadeIn {
148
+ from { opacity: 0; }
149
+ to { opacity: 1; }
150
+ }
151
+ @keyframes slideUp {
152
+ from { transform: translateY(20px); opacity: 0; }
153
+ to { transform: translateY(0); opacity: 1; }
154
+ }
155
+ </style>
156
+ <div class='fade-in'>
157
+ <h1 style="text-align:center; font-size: 2.4em;">πŸ‘‹ Welcome to Your Personalized AI Agent Demo ✨</h1>
158
+ <p style="text-align:center; font-size: 1.2em;">πŸš€ Automate marketing, save time, and scale smartly using AI Agents</p>
159
+ </div>
160
+ """, visible=True)
161
+
162
+ with gr.Column(visible=True) as setup_page:
163
+
164
+ with gr.Group(elem_classes=["slide-up", "section"]):
165
+ gr.Markdown("### πŸ’Ό What’s the name of your company/service?")
166
+ company_name = gr.Textbox(lines=1, placeholder="e.g., SwiftSync AI")
167
+
168
+ with gr.Group(elem_classes=["slide-up", "section"]):
169
+ gr.Markdown("### πŸ“ Tell us briefly what your company does:")
170
+ company_desc = gr.Textbox(lines=3, placeholder="We provide AI-driven automation tools...")
171
+
172
+ with gr.Group(elem_classes=["slide-up", "section"]):
173
+ gr.Markdown("### πŸ“„ Got a business PDF? Upload it here to make your AI Agent smarter:")
174
+ pdf_file = gr.File(file_types=[".pdf"], label="Upload your PDF")
175
+
176
+ with gr.Group(elem_classes=["slide-up"]):
177
+ setup_submit = gr.Button("✨ Build My Agent Now")
178
+
179
+ with gr.Column(visible=False) as processing_page:
180
+ processing_msg = gr.HTML("""
181
+ <style>
182
+ @keyframes spin {
183
+ 0% { transform: rotate(0deg); }
184
+ 100% { transform: rotate(360deg); }
185
+ }
186
+ @keyframes fade {
187
+ 0%, 100% { opacity: 0.2; }
188
+ 50% { opacity: 1; }
189
+ }
190
+ .loader {
191
+ border: 6px solid #e0e0e0;
192
+ border-top: 6px solid #00bcd4;
193
+ border-radius: 50%;
194
+ width: 50px;
195
+ height: 50px;
196
+ animation: spin 1s linear infinite;
197
+ box-shadow: 0 0 10px rgba(0,188,212,0.4);
198
+ }
199
+ .processing-text {
200
+ font-size: 1.1em;
201
+ margin-top: 15px;
202
+ font-weight: 500;
203
+ color: #555;
204
+ animation: fade 2s infinite ease-in-out;
205
+ }
206
+ </style>
207
+
208
+ <div style="display: flex; flex-direction: column; align-items: center; margin-top: 40px;">
209
+ <div class="loader"></div>
210
+ <div class="processing-text">🧠 Building your AI Agent...</div>
211
+ </div>
212
+ """, visible=True)
213
+
214
+ with gr.Column(visible=False) as agent_page:
215
+ # Header Section
216
+ gr.HTML("""
217
+ <style>
218
+ .title-box {
219
+ text-align: center;
220
+ padding: 15px 0;
221
+ background: linear-gradient(90deg, #007bff 0%, #00c2ff 100%);
222
+ color: white;
223
+ border-radius: 12px;
224
+ box-shadow: 0 4px 10px rgba(0,0,0,0.15);
225
+ }
226
+ .info-card {
227
+ background: #f9f9f9;
228
+ border-left: 4px solid #007bff;
229
+ padding: 12px 20px;
230
+ border-radius: 8px;
231
+ font-size: 15px;
232
+ margin-bottom: 20px;
233
+ color: #333;
234
+ }
235
+ .query-area {
236
+ padding: 20px;
237
+ border-radius: 12px;
238
+ background: #fff;
239
+ box-shadow: 0 2px 8px rgba(0,0,0,0.08);
240
+ }
241
+ .footer-note {
242
+ text-align: center;
243
+ color: #888;
244
+ font-size: 13.5px;
245
+ padding: 15px 0;
246
+ margin-top: 20px;
247
+ }
248
+ </style>
249
+
250
+ <div class="title-box">
251
+ <h1>🧠 Your Personalized AI Agent</h1>
252
+ <p style="margin-top: -10px;">Supercharged for Safety, Relevance, and Results</p>
253
+ </div>
254
+ """)
255
+ gr.HTML("""
256
+ <style>
257
+ .built-by-card {
258
+ margin-top: 30px;
259
+ padding: 15px;
260
+ background: #f0f4ff;
261
+ color: #333;
262
+ text-align: center;
263
+ border-radius: 12px;
264
+ font-size: 14px;
265
+ box-shadow: 0 2px 8px rgba(0,0,0,0.05);
266
+ font-weight: 500;
267
+ transition: all 0.3s ease;
268
+ }
269
+ .built-by-card:hover {
270
+ box-shadow: 0 4px 14px rgba(0,0,0,0.1);
271
+ background: #e6f0ff;
272
+ }
273
+ </style>
274
+
275
+ <div class="built-by-card">
276
+ πŸš€ Built with ❀️ by <strong>Darsh Tayal</strong>
277
+ </div>
278
+ """, visible = True)
279
+
280
+
281
+ # Company Description
282
+ comp_descri = gr.Markdown("")
283
+
284
+ # Agent Info Features
285
+ gr.HTML("""
286
+ <div class="info-card">
287
+ βœ… This agent uses a <strong>relevance checker</strong> to block off-topic questions.<br>
288
+ πŸ”’ It also runs a <strong>safety filter</strong> to protect users from harmful content.<br>
289
+ πŸ•’ <em>Saving your time while keeping things secure.</em>
290
+ </div>
291
+ """)
292
+
293
+ # Query Section
294
+ gr.HTML("<div class='query-area'>")
295
+ gr.Markdown("### πŸ’¬ Ask something related to your business/service:")
296
+ query = gr.Textbox(lines=2, placeholder="e.g., What are the top 3 features of our service?")
297
+ agent_submit = gr.Button("πŸš€ Submit Query")
298
+ loading_spinner = gr.HTML("""
299
+ <style>
300
+ @keyframes spin {
301
+ 0% { transform: rotate(0deg); }
302
+ 100% { transform: rotate(360deg); }
303
+ }
304
+ .loader {
305
+ border: 5px solid #f3f3f3;
306
+ border-top: 5px solid #00bcd4;
307
+ border-radius: 50%;
308
+ width: 40px;
309
+ height: 40px;
310
+ animation: spin 1s linear infinite;
311
+ }
312
+ .loading-text {
313
+ margin-top: 8px;
314
+ color: #666;
315
+ font-size: 14px;
316
+ animation: pulse 1.8s infinite ease-in-out;
317
+ }
318
+ @keyframes pulse {
319
+ 0%, 100% { opacity: 0.4; }
320
+ 50% { opacity: 1; }
321
+ }
322
+ </style>
323
+ <div style="display:flex; flex-direction:column; align-items:center; margin-top: 10px;" id="spinner">
324
+ <div class="loader"></div>
325
+ <div class="loading-text">Thinking... generating magic ✨</div>
326
+ </div>
327
+ """, visible=False)
328
+
329
+ answer = gr.TextArea(label='πŸ€– AI Response', lines=4, interactive=False)
330
+ gr.HTML("</div>") # Close .query-area div
331
+
332
+ # Footer CTA
333
+ gr.HTML("""
334
+ <div class="footer-note">
335
+ πŸ’‘ This was just a general demo. Want a version tailored to your business?<br>
336
+ πŸ‘‰ Email me at <strong>[email protected]</strong><br>
337
+ πŸ“ˆ We can connect this agent to whatsapp, or any other marketing channel you use<br>
338
+ βš™οΈ Start automating, or get left behind.
339
+ </div>
340
+ """)
341
+ setup_submit.click(fn=setter, inputs=[pdf_file, company_desc, company_name], outputs=[setup_page, processing_page, agent_page, header, comp_descri, company_generated_description, vectorstore_db])
342
+ agent_submit.click(fn=chat, inputs=[query, vectorstore_db, company_generated_description], outputs=[loading_spinner, answer])
343
+ ui.launch()
README.md CHANGED
@@ -1,12 +1,6 @@
1
  ---
2
- title: Darshs Project
3
- emoji: πŸ†
4
- colorFrom: gray
5
- colorTo: indigo
6
  sdk: gradio
7
- sdk_version: 5.35.0
8
- app_file: app.py
9
- pinned: false
10
  ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: Darshs_project
3
+ app_file: demo project.py
 
 
4
  sdk: gradio
5
+ sdk_version: 5.23.1
 
 
6
  ---
 
 
demo project.py ADDED
@@ -0,0 +1,341 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from langchain_groq import ChatGroq
3
+ import os
4
+ from langgraph.graph import StateGraph, START, END
5
+ from langchain_text_splitters import RecursiveCharacterTextSplitter
6
+ from langchain_chroma import Chroma
7
+ from typing import Annotated
8
+ from typing_extensions import TypedDict
9
+ from pydantic import BaseModel, Field
10
+ from langchain_core.messages import HumanMessage
11
+ import time
12
+ import os
13
+ from langchain_community.document_loaders import PyPDFLoader
14
+ from langchain_huggingface import HuggingFaceEmbeddings
15
+
16
+ class State(TypedDict):
17
+ query: str
18
+ is_safe: bool
19
+ is_relevant: bool
20
+ company_description: str
21
+ answer: str
22
+ vectorstoredb: Chroma
23
+
24
+ class checker_class(BaseModel):
25
+ is_relevant: bool = Field(description="Check whether the given query is relevant to the company.")
26
+
27
+ def invoke_llm(query):
28
+ llm = ChatGroq(model='llama-3.3-70b-versatile')
29
+ try:
30
+ res = llm.invoke(query)
31
+ except:
32
+ time.sleep(60)
33
+ res = llm.invoke(query)
34
+ return res.content
35
+
36
+ def invoke_relevance_checker_llm(query):
37
+ llm = ChatGroq(model='gemma2-9b-it')
38
+ checker_llm = llm.with_structured_output(checker_class)
39
+ try:
40
+ res = checker_llm.invoke([HumanMessage(content=query)])
41
+ except:
42
+ time.sleep(60)
43
+ res = checker_llm.invoke([HumanMessage(content=query)])
44
+ return res.is_relevant
45
+
46
+ def safety_checker(state:State):
47
+ llm = ChatGroq(model='meta-llama/llama-guard-4-12b')
48
+ query = state['query']
49
+ res = llm.invoke(query)
50
+ if res.content == 'safe':
51
+ return {'is_safe':True}
52
+ else:
53
+ return {'is_safe':False, 'answer':"<SAFETY CHECKER> That prompt was harmful, please try something else"}
54
+
55
+ def relevance_checker(state:State):
56
+ prompt = "You are a lenient relevance-checking assistant. You will be given a user query and a company description. Your job is to decide whether the query is relevant to the company.\nβœ… Approve most queries that are even loosely related.\n🚫 Only reject queries that are **clearly unrelated** or have **no connection at all**.\n\n"
57
+ prompt += f"\nQuery: {state['query']}"
58
+ prompt += f"\nDescription: {state['company_description']}"
59
+ res = invoke_relevance_checker_llm(prompt)
60
+ return {'is_relevant':res, 'answer':"Sorry! That doesn't seem to be relevant to us, please try something else."}
61
+
62
+ def agent(state:State):
63
+ relevant_text = ""
64
+ search_docs = state['vectorstoredb'].similarity_search(state['query'])
65
+ for chunk in search_docs:
66
+ relevant_text += f"\n{chunk.page_content}"
67
+ prompt = f"You have to answer this query: {state['query']} based only on the following information: {relevant_text}. Reply only with the answer."
68
+ try:
69
+ res = invoke_llm(prompt)
70
+ except:
71
+ time.sleep(60)
72
+ res = invoke_llm(prompt)
73
+ finally:
74
+ return {'answer':res}
75
+
76
+ def safety_assigner(state:State):
77
+ if state['is_safe']:
78
+ return 'relevant'
79
+ else:
80
+ return 'END'
81
+
82
+ def relevant_assigner(state:State):
83
+ if state['is_relevant']:
84
+ return 'Agent'
85
+ else:
86
+ return 'END'
87
+
88
+ def chat(query, vect, dec):
89
+ yield gr.update(visible=True), ""
90
+ mess = {'query':query, 'vectorstoredb': vect, 'company_description': dec}
91
+ res = graph.invoke(mess)
92
+ yield gr.update(visible=False), res['answer']
93
+
94
+ def setter(pdf_file, description, company_name):
95
+ yield gr.update(visible=False), gr.update(visible=True), gr.update(visible=False), gr.update(visible=False), "", "", ""
96
+ loader = PyPDFLoader(pdf_file)
97
+ docs = loader.load()
98
+ consise_pdf = docs[1].page_content if len(docs) > 1 else docs[0].page_content
99
+ consise_pdf = consise_pdf[:5555]
100
+ full_pdf = ""
101
+ for content in docs:
102
+ full_pdf += f"\n{content.page_content}"
103
+ embeddings = HuggingFaceEmbeddings(model_name='sentence-transformers/all-mpnet-base-v2')
104
+ splitter = RecursiveCharacterTextSplitter(chunk_size=400, chunk_overlap=100)
105
+ chunks = splitter.split_text(full_pdf)
106
+ vector_db = Chroma.from_texts(chunks, embeddings)
107
+ prompt = "You are a company description generator assistant. "
108
+ prompt += "You will be given the name of a company, a short description provided by the owner, "
109
+ prompt += "and additional content extracted from a company file (such as a brochure or document). "
110
+ prompt += "Using this information, generate a concise and professional 3–4 line description of the company. Also, reply in markdown\n\n"
111
+ prompt += f"Company Name: {company_name}\n"
112
+ prompt += f"Owner's Description: {description}\n"
113
+ prompt += f"File Content: {consise_pdf}\n"
114
+ prompt += "Final Description:"
115
+ response = invoke_llm(prompt)
116
+ yield gr.update(visible=False), gr.update(visible=False), gr.update(visible=True), gr.update(visible=False), response, response, vector_db
117
+
118
+ builder = StateGraph(State)
119
+
120
+ builder.add_node("Safety Checker", safety_checker)
121
+ builder.add_node("Relevance Checker", relevance_checker)
122
+ builder.add_node("Agent", agent)
123
+
124
+ builder.add_edge(START, "Safety Checker")
125
+ builder.add_conditional_edges("Safety Checker", safety_assigner, {'relevant':"Relevance Checker", 'END': END})
126
+ builder.add_conditional_edges("Relevance Checker", relevant_assigner, {'Agent':"Agent", 'END':END})
127
+ builder.add_edge("Agent",END)
128
+
129
+ graph = builder.compile()
130
+
131
+ with gr.Blocks(css=".section {margin-bottom: 20px;}") as ui:
132
+
133
+ vectorstore_db = gr.State()
134
+ company_generated_description = gr.State()
135
+
136
+ # πŸŒ€ CSS + HTML animation injection
137
+ header = gr.HTML("""
138
+ <style>
139
+ .fade-in {
140
+ animation: fadeIn 1.2s ease-in;
141
+ }
142
+ .slide-up {
143
+ animation: slideUp 0.8s ease-out;
144
+ }
145
+ @keyframes fadeIn {
146
+ from { opacity: 0; }
147
+ to { opacity: 1; }
148
+ }
149
+ @keyframes slideUp {
150
+ from { transform: translateY(20px); opacity: 0; }
151
+ to { transform: translateY(0); opacity: 1; }
152
+ }
153
+ </style>
154
+ <div class='fade-in'>
155
+ <h1 style="text-align:center; font-size: 2.4em;">πŸ‘‹ Welcome to Your Personalized AI Agent Demo ✨</h1>
156
+ <p style="text-align:center; font-size: 1.2em;">πŸš€ Automate marketing, save time, and scale smartly using AI Agents</p>
157
+ </div>
158
+ """, visible=True)
159
+
160
+ with gr.Column(visible=True) as setup_page:
161
+
162
+ with gr.Group(elem_classes=["slide-up", "section"]):
163
+ gr.Markdown("### πŸ’Ό What’s the name of your company/service?")
164
+ company_name = gr.Textbox(lines=1, placeholder="e.g., SwiftSync AI")
165
+
166
+ with gr.Group(elem_classes=["slide-up", "section"]):
167
+ gr.Markdown("### πŸ“ Tell us briefly what your company does:")
168
+ company_desc = gr.Textbox(lines=3, placeholder="We provide AI-driven automation tools...")
169
+
170
+ with gr.Group(elem_classes=["slide-up", "section"]):
171
+ gr.Markdown("### πŸ“„ Got a business PDF? Upload it here to make your AI Agent smarter:")
172
+ pdf_file = gr.File(file_types=[".pdf"], label="Upload your PDF")
173
+
174
+ with gr.Group(elem_classes=["slide-up"]):
175
+ setup_submit = gr.Button("✨ Build My Agent Now")
176
+
177
+ with gr.Column(visible=False) as processing_page:
178
+ processing_msg = gr.HTML("""
179
+ <style>
180
+ @keyframes spin {
181
+ 0% { transform: rotate(0deg); }
182
+ 100% { transform: rotate(360deg); }
183
+ }
184
+ @keyframes fade {
185
+ 0%, 100% { opacity: 0.2; }
186
+ 50% { opacity: 1; }
187
+ }
188
+ .loader {
189
+ border: 6px solid #e0e0e0;
190
+ border-top: 6px solid #00bcd4;
191
+ border-radius: 50%;
192
+ width: 50px;
193
+ height: 50px;
194
+ animation: spin 1s linear infinite;
195
+ box-shadow: 0 0 10px rgba(0,188,212,0.4);
196
+ }
197
+ .processing-text {
198
+ font-size: 1.1em;
199
+ margin-top: 15px;
200
+ font-weight: 500;
201
+ color: #555;
202
+ animation: fade 2s infinite ease-in-out;
203
+ }
204
+ </style>
205
+
206
+ <div style="display: flex; flex-direction: column; align-items: center; margin-top: 40px;">
207
+ <div class="loader"></div>
208
+ <div class="processing-text">🧠 Building your AI Agent...</div>
209
+ </div>
210
+ """, visible=True)
211
+
212
+ with gr.Column(visible=False) as agent_page:
213
+ # Header Section
214
+ gr.HTML("""
215
+ <style>
216
+ .title-box {
217
+ text-align: center;
218
+ padding: 15px 0;
219
+ background: linear-gradient(90deg, #007bff 0%, #00c2ff 100%);
220
+ color: white;
221
+ border-radius: 12px;
222
+ box-shadow: 0 4px 10px rgba(0,0,0,0.15);
223
+ }
224
+ .info-card {
225
+ background: #f9f9f9;
226
+ border-left: 4px solid #007bff;
227
+ padding: 12px 20px;
228
+ border-radius: 8px;
229
+ font-size: 15px;
230
+ margin-bottom: 20px;
231
+ color: #333;
232
+ }
233
+ .query-area {
234
+ padding: 20px;
235
+ border-radius: 12px;
236
+ background: #fff;
237
+ box-shadow: 0 2px 8px rgba(0,0,0,0.08);
238
+ }
239
+ .footer-note {
240
+ text-align: center;
241
+ color: #888;
242
+ font-size: 13.5px;
243
+ padding: 15px 0;
244
+ margin-top: 20px;
245
+ }
246
+ </style>
247
+
248
+ <div class="title-box">
249
+ <h1>🧠 Your Personalized AI Agent</h1>
250
+ <p style="margin-top: -10px;">Supercharged for Safety, Relevance, and Results</p>
251
+ </div>
252
+ """)
253
+ gr.HTML("""
254
+ <style>
255
+ .built-by-card {
256
+ margin-top: 30px;
257
+ padding: 15px;
258
+ background: #f0f4ff;
259
+ color: #333;
260
+ text-align: center;
261
+ border-radius: 12px;
262
+ font-size: 14px;
263
+ box-shadow: 0 2px 8px rgba(0,0,0,0.05);
264
+ font-weight: 500;
265
+ transition: all 0.3s ease;
266
+ }
267
+ .built-by-card:hover {
268
+ box-shadow: 0 4px 14px rgba(0,0,0,0.1);
269
+ background: #e6f0ff;
270
+ }
271
+ </style>
272
+
273
+ <div class="built-by-card">
274
+ πŸš€ Built with ❀️ by <strong>Darsh Tayal</strong>
275
+ </div>
276
+ """, visible = True)
277
+
278
+
279
+ # Company Description
280
+ comp_descri = gr.Markdown("")
281
+
282
+ # Agent Info Features
283
+ gr.HTML("""
284
+ <div class="info-card">
285
+ βœ… This agent uses a <strong>relevance checker</strong> to block off-topic questions.<br>
286
+ πŸ”’ It also runs a <strong>safety filter</strong> to protect users from harmful content.<br>
287
+ πŸ•’ <em>Saving your time while keeping things secure.</em>
288
+ </div>
289
+ """)
290
+
291
+ # Query Section
292
+ gr.HTML("<div class='query-area'>")
293
+ gr.Markdown("### πŸ’¬ Ask something related to your business/service:")
294
+ query = gr.Textbox(lines=2, placeholder="e.g., What are the top 3 features of our service?")
295
+ agent_submit = gr.Button("πŸš€ Submit Query")
296
+ loading_spinner = gr.HTML("""
297
+ <style>
298
+ @keyframes spin {
299
+ 0% { transform: rotate(0deg); }
300
+ 100% { transform: rotate(360deg); }
301
+ }
302
+ .loader {
303
+ border: 5px solid #f3f3f3;
304
+ border-top: 5px solid #00bcd4;
305
+ border-radius: 50%;
306
+ width: 40px;
307
+ height: 40px;
308
+ animation: spin 1s linear infinite;
309
+ }
310
+ .loading-text {
311
+ margin-top: 8px;
312
+ color: #666;
313
+ font-size: 14px;
314
+ animation: pulse 1.8s infinite ease-in-out;
315
+ }
316
+ @keyframes pulse {
317
+ 0%, 100% { opacity: 0.4; }
318
+ 50% { opacity: 1; }
319
+ }
320
+ </style>
321
+ <div style="display:flex; flex-direction:column; align-items:center; margin-top: 10px;" id="spinner">
322
+ <div class="loader"></div>
323
+ <div class="loading-text">Thinking... generating magic ✨</div>
324
+ </div>
325
+ """, visible=False)
326
+
327
+ answer = gr.TextArea(label='πŸ€– AI Response', lines=4, interactive=False)
328
+ gr.HTML("</div>") # Close .query-area div
329
+
330
+ # Footer CTA
331
+ gr.HTML("""
332
+ <div class="footer-note">
333
+ πŸ’‘ This was just a general demo. Want a version tailored to your business?<br>
334
+ πŸ‘‰ Email me at <strong>[email protected]</strong><br>
335
+ πŸ“ˆ We can connect this agent to whatsapp, or any other marketing channel you use<br>
336
+ βš™οΈ Start automating, or get left behind.
337
+ </div>
338
+ """)
339
+ setup_submit.click(fn=setter, inputs=[pdf_file, company_desc, company_name], outputs=[setup_page, processing_page, agent_page, header, comp_descri, company_generated_description, vectorstore_db])
340
+ agent_submit.click(fn=chat, inputs=[query, vectorstore_db, company_generated_description], outputs=[loading_spinner, answer])
341
+ ui.launch()
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ gradio
2
+ langchain
3
+ langchain-groq
4
+ langgraph
5
+ langchain-text-splitters
6
+ langchain-chroma
7
+ langchain-community
8
+ langchain-huggingface
9
+ pydantic
10
+ typing-extensions