Spaces:
Running
Running
added ability to show passages
Browse files- app.py +118 -94
- app2.py +120 -0
- app_multi_tab.py +107 -0
- notebooks/01 Basic Chatbot.ipynb +26 -28
- notebooks/02 Chatbot with custom system prompt.ipynb +287 -0
- notebooks/03 Experimentation Chatbot.ipynb +368 -151
- notebooks/04 Return Passages.ipynb +0 -0
- notebooks/05 Scratch.ipynb +0 -0
- prompts/system_prompts.py +34 -44
- src/srf_bot.py +172 -0
app.py
CHANGED
@@ -1,106 +1,130 @@
|
|
1 |
import gradio as gr
|
|
|
|
|
|
|
2 |
|
3 |
-
#
|
4 |
-
|
5 |
-
"Friendly Chatbot": "You are a helpful, friendly chatbot that engages in light-hearted conversations.",
|
6 |
-
"Technical Assistant": "You are a technical assistant specialized in answering questions related to Python programming.",
|
7 |
-
"Nutrition Advisor": "You provide evidence-based advice on nutrition and healthy eating habits.",
|
8 |
-
}
|
9 |
|
10 |
-
# Define
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
|
17 |
-
# Chatbot logic for custom instructions or pre-written templates
|
18 |
-
def chatbot_response(system_instructions, user_query):
|
19 |
-
if "friendly" in system_instructions.lower():
|
20 |
-
return f"Friendly Chatbot says: Hi there! 😊 How can I assist you today?"
|
21 |
-
elif "technical" in system_instructions.lower():
|
22 |
-
return f"Technical Assistant says: Sure! Here's some information on Python: {user_query}"
|
23 |
-
elif "nutrition" in system_instructions.lower():
|
24 |
-
return f"Nutrition Advisor says: Here's some advice about healthy eating: {user_query}"
|
25 |
-
else:
|
26 |
-
return f"Custom Chatbot says: {user_query}"
|
27 |
|
28 |
-
#
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
|
51 |
-
#
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
with gr.
|
56 |
-
gr.Markdown("""
|
57 |
-
<div style='background-color:#E0E0E0; padding: 20px; border-radius: 10px;'>
|
58 |
-
<h1 style='text-align: center; color: #1E3A8A;'>SRF Innovation Labs - AI Chatbot Use Case Explorer</h1>
|
59 |
-
<p style='font-size: 18px; text-align: center; color: #1E3A8A;'>
|
60 |
-
This tool allows you to experiment with different system prompts,
|
61 |
-
giving you control over how the chatbot behaves. You can either use pre-defined templates
|
62 |
-
or write your own custom instructions.
|
63 |
-
</p>
|
64 |
-
</div>
|
65 |
-
""")
|
66 |
-
|
67 |
-
# Section to select system instructions from dropdown
|
68 |
-
gr.Markdown("<h2 style='color: #1E3A8A;'>Chatbot Setup</h2>")
|
69 |
-
template_name = gr.Dropdown(choices=["Custom Instructions"] + list(templates.keys()), label="Choose Instructions", value="Friendly Chatbot")
|
70 |
-
custom_instructions = gr.Textbox(label="Custom Instructions", visible=False, placeholder="Write your own instructions here...")
|
71 |
-
template_display = gr.Textbox(label="Template Content", interactive=False, visible=True)
|
72 |
-
|
73 |
# Chatbot interface
|
74 |
-
gr.
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
#
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
gr.Markdown("""
|
86 |
-
<div
|
87 |
-
<
|
88 |
-
<
|
89 |
-
|
90 |
-
|
91 |
-
|
|
|
92 |
</div>
|
93 |
""")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
|
95 |
-
|
96 |
-
workflow_name = gr.Dropdown(choices=list(agentic_workflows.keys()), label="Choose Agent Workflow", value="Blog Post Generator")
|
97 |
-
workflow_display = gr.Textbox(label="Workflow Description", interactive=False, visible=True)
|
98 |
-
workflow_chatbot = gr.Chatbot(label="Agent Workflow Conversation", height=300, show_label=False)
|
99 |
-
workflow_user_query = gr.Textbox(label="Your Query", placeholder="Ask the agent to perform a task...")
|
100 |
-
workflow_submit_button = gr.Button("Send", elem_classes=["gr-button"])
|
101 |
-
|
102 |
-
# Chatbot interaction for agentic workflows
|
103 |
-
workflow_submit_button.click(fn=agentic_chatbot_conversation, inputs=[workflow_name, workflow_chatbot, workflow_user_query], outputs=[workflow_chatbot, workflow_user_query])
|
104 |
-
|
105 |
-
# Launch the app
|
106 |
demo.launch()
|
|
|
1 |
import gradio as gr
|
2 |
+
import src.srf_bot as sb
|
3 |
+
import prompts.system_prompts as sp
|
4 |
+
from langchain_core.messages import HumanMessage
|
5 |
|
6 |
+
# Initialize chatbot
|
7 |
+
chatbot = sb.SRFChatbot()
|
|
|
|
|
|
|
|
|
8 |
|
9 |
+
# Define the respond function
|
10 |
+
def respond(query, history):
|
11 |
+
formatted_query = [HumanMessage(content=query)]
|
12 |
+
# Invoke the graph with properly formatted input
|
13 |
+
result = chatbot.graph.invoke({"messages": formatted_query}, chatbot.config)
|
14 |
+
# Get the passages from the graph and append to history if documents exist
|
15 |
+
state = chatbot.graph.get_state(config=chatbot.config).values
|
16 |
+
documents = state.get("documents")
|
17 |
+
passages = ''
|
18 |
+
if documents and len(documents) > 0:
|
19 |
+
for d in documents:
|
20 |
+
passages += f'<b>{d.metadata["publication_name"]} - {d.metadata["chapter_name"]}</b>\n{d.page_content}\n\n'
|
21 |
+
history.append((f'Passages: {query}', passages))
|
22 |
+
# Extract the assistant's response and append to history
|
23 |
+
response = result["messages"][-1].content
|
24 |
+
system_message_dropdown = state.get("system_message_dropdown")
|
25 |
+
history.append((query, f"<i>[{system_message_dropdown}]</i>\n" + response))
|
26 |
+
return history
|
27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
|
29 |
+
# Gradio interface with black and grey color scheme
|
30 |
+
with gr.Blocks(css="""
|
31 |
+
.gradio-container {
|
32 |
+
background-color: #F0F0F0;
|
33 |
+
font-family: 'Arial', sans-serif;
|
34 |
+
}
|
35 |
+
h1, h2, p {
|
36 |
+
color: black;
|
37 |
+
}
|
38 |
+
h1 {
|
39 |
+
font-size: 32px;
|
40 |
+
text-align: left;
|
41 |
+
}
|
42 |
+
h2 {
|
43 |
+
font-size: 24px;
|
44 |
+
}
|
45 |
+
p {
|
46 |
+
font-size: 18px;
|
47 |
+
margin-bottom: 15px;
|
48 |
+
}
|
49 |
+
.gr-button {
|
50 |
+
background-color: #333333;
|
51 |
+
color: white;
|
52 |
+
font-size: 18px;
|
53 |
+
padding: 10px;
|
54 |
+
}
|
55 |
+
.gr-textbox textarea {
|
56 |
+
font-size: 18px;
|
57 |
+
color: black;
|
58 |
+
}
|
59 |
+
.gr-dropdown {
|
60 |
+
font-size: 18px;
|
61 |
+
color: black;
|
62 |
+
}
|
63 |
+
.source-box {
|
64 |
+
background-color: white;
|
65 |
+
padding: 10px;
|
66 |
+
border-radius: 8px;
|
67 |
+
margin-top: 20px;
|
68 |
+
color: black;
|
69 |
+
border: 1px solid #D0D0D0;
|
70 |
+
}
|
71 |
+
@media (max-width: 600px) {
|
72 |
+
.gr-row { flex-direction: column !important; }
|
73 |
+
.gr-column { width: 100% !important; }
|
74 |
+
}
|
75 |
+
""") as demo:
|
76 |
|
77 |
+
# Title
|
78 |
+
gr.Markdown("# SRF Chatbot")
|
79 |
+
|
80 |
+
with gr.Row(elem_classes="gr-row"):
|
81 |
+
with gr.Column(scale=4, elem_classes="gr-column"):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
# Chatbot interface
|
83 |
+
chatbot_output = gr.Chatbot(height=600) # Increased height for longer chat interface
|
84 |
+
user_input = gr.Textbox(placeholder="Type your question here...", label="Your Question", value="What is the meaning of life?")
|
85 |
+
submit_button = gr.Button("Submit")
|
86 |
+
|
87 |
+
with gr.Column(scale=1, elem_classes="gr-column"):
|
88 |
+
# Dropdown to select system prompts
|
89 |
+
system_prompt_dropdown = gr.Dropdown(
|
90 |
+
choices=list(sp.system_prompt_templates.keys()),
|
91 |
+
label="Select Chatbot Instructions",
|
92 |
+
value=list(sp.system_prompt_templates.keys())[0],
|
93 |
+
elem_classes="gr-dropdown"
|
94 |
+
)
|
95 |
+
# Display the selected system prompt
|
96 |
+
system_prompt_display = gr.Textbox(
|
97 |
+
value=sp.system_prompt_templates[list(sp.system_prompt_templates.keys())[0]],
|
98 |
+
label="Current Chatbot Instructions",
|
99 |
+
lines=5,
|
100 |
+
interactive=False
|
101 |
+
)
|
102 |
+
|
103 |
+
# Sources box (Now white, matching the other boxes)
|
104 |
gr.Markdown("""
|
105 |
+
<div class="source-box">
|
106 |
+
<strong>Available sources:</strong>
|
107 |
+
<ul>
|
108 |
+
<li>Journey to Self-Realization</li>
|
109 |
+
<li>The Second Coming of Christ</li>
|
110 |
+
<li>Autobiography of a Yogi</li>
|
111 |
+
</ul>
|
112 |
</div>
|
113 |
""")
|
114 |
+
|
115 |
+
# Update system prompt display when a new prompt is selected
|
116 |
+
system_prompt_dropdown.change(
|
117 |
+
fn=chatbot.reset_system_prompt,
|
118 |
+
inputs=[system_prompt_dropdown],
|
119 |
+
outputs=[system_prompt_display]
|
120 |
+
)
|
121 |
+
|
122 |
+
# Submit button logic to handle chatbot conversation
|
123 |
+
submit_button.click(
|
124 |
+
fn=respond,
|
125 |
+
inputs=[user_input, chatbot_output],
|
126 |
+
outputs=[chatbot_output]
|
127 |
+
)
|
128 |
|
129 |
+
# Launch the interface
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
130 |
demo.launch()
|
app2.py
ADDED
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import src.srf_bot as sb
|
3 |
+
import prompts.system_prompts as sp
|
4 |
+
from langchain_core.messages import HumanMessage
|
5 |
+
|
6 |
+
# Initialize the chatbot
|
7 |
+
chatbot = sb.SRFChatbot()
|
8 |
+
|
9 |
+
# Dictionary to store passages with identifiers
|
10 |
+
retrieved_passages = {}
|
11 |
+
|
12 |
+
# Define the respond function
|
13 |
+
def respond(query, history):
|
14 |
+
formatted_query = [HumanMessage(content=query)]
|
15 |
+
# Invoke the chatbot
|
16 |
+
result = chatbot.graph.invoke({"messages": formatted_query}, chatbot.config)
|
17 |
+
|
18 |
+
# Extract the assistant's response
|
19 |
+
response = result["messages"][-1].content
|
20 |
+
|
21 |
+
# Retrieve passages from your vector database based on the query
|
22 |
+
# For the example, we'll use dummy passages
|
23 |
+
passages = [
|
24 |
+
"This is the full text of Passage 1.",
|
25 |
+
"This is the full text of Passage 2.",
|
26 |
+
"This is the full text of Passage 3."
|
27 |
+
]
|
28 |
+
|
29 |
+
# Store passages with identifiers
|
30 |
+
passage_ids = []
|
31 |
+
for idx, passage in enumerate(passages):
|
32 |
+
identifier = f"Passage {idx+1}"
|
33 |
+
retrieved_passages[identifier] = passage
|
34 |
+
passage_ids.append(identifier)
|
35 |
+
|
36 |
+
# Reference passages in the response
|
37 |
+
linked_response = f"{response}\n\nReferences:"
|
38 |
+
for pid in passage_ids:
|
39 |
+
linked_response += f" [{pid}]"
|
40 |
+
|
41 |
+
# Append to history
|
42 |
+
history.append((query, linked_response))
|
43 |
+
return history, ""
|
44 |
+
|
45 |
+
# Function to get passage content based on selection
|
46 |
+
def get_passage_content(passage_id):
|
47 |
+
return retrieved_passages.get(passage_id, "Passage not found.")
|
48 |
+
|
49 |
+
# Function to update the system prompt
|
50 |
+
def update_system_prompt(selected_prompt):
|
51 |
+
# Update the chatbot's system prompt
|
52 |
+
chatbot.reset_system_prompt(selected_prompt)
|
53 |
+
# Update the displayed system prompt text
|
54 |
+
return sp.system_prompt_templates[selected_prompt]
|
55 |
+
|
56 |
+
# Gradio interface
|
57 |
+
with gr.Blocks() as demo:
|
58 |
+
gr.Markdown("# SRF Chatbot")
|
59 |
+
|
60 |
+
with gr.Row():
|
61 |
+
with gr.Column(scale=4):
|
62 |
+
# Chatbot interface
|
63 |
+
chatbot_output = gr.Chatbot()
|
64 |
+
user_input = gr.Textbox(placeholder="Type your question here...", label="Your Question")
|
65 |
+
submit_button = gr.Button("Submit")
|
66 |
+
|
67 |
+
with gr.Column(scale=1):
|
68 |
+
# Dropdown to select system prompts
|
69 |
+
system_prompt_dropdown = gr.Dropdown(
|
70 |
+
choices=list(sp.system_prompt_templates.keys()),
|
71 |
+
label="Select Chatbot Instructions",
|
72 |
+
value=list(sp.system_prompt_templates.keys())[0]
|
73 |
+
)
|
74 |
+
# Display the selected system prompt
|
75 |
+
system_prompt_display = gr.Textbox(
|
76 |
+
value=sp.system_prompt_templates[list(sp.system_prompt_templates.keys())[0]],
|
77 |
+
label="Current Chatbot Instructions",
|
78 |
+
lines=5,
|
79 |
+
interactive=False
|
80 |
+
)
|
81 |
+
|
82 |
+
# Update system prompt display when a new prompt is selected
|
83 |
+
system_prompt_dropdown.change(
|
84 |
+
fn=update_system_prompt,
|
85 |
+
inputs=[system_prompt_dropdown],
|
86 |
+
outputs=[system_prompt_display]
|
87 |
+
)
|
88 |
+
|
89 |
+
# Passage selection and display
|
90 |
+
gr.Markdown("### References")
|
91 |
+
passage_selector = gr.Dropdown(label="Select a passage to view", choices=[])
|
92 |
+
passage_display = gr.Markdown()
|
93 |
+
|
94 |
+
# Update the chatbot when the submit button is clicked
|
95 |
+
submit_button.click(
|
96 |
+
fn=respond,
|
97 |
+
inputs=[user_input, chatbot_output],
|
98 |
+
outputs=[chatbot_output, user_input]
|
99 |
+
)
|
100 |
+
|
101 |
+
# Update the passage selector options when the chatbot output changes
|
102 |
+
def update_passage_selector(chat_history):
|
103 |
+
# Get the latest passages
|
104 |
+
choices = list(retrieved_passages.keys())
|
105 |
+
return gr.update(choices=choices)
|
106 |
+
|
107 |
+
chatbot_output.change(
|
108 |
+
fn=update_passage_selector,
|
109 |
+
inputs=[chatbot_output],
|
110 |
+
outputs=[passage_selector]
|
111 |
+
)
|
112 |
+
|
113 |
+
# Display the selected passage
|
114 |
+
passage_selector.change(
|
115 |
+
fn=get_passage_content,
|
116 |
+
inputs=[passage_selector],
|
117 |
+
outputs=[passage_display]
|
118 |
+
)
|
119 |
+
|
120 |
+
demo.launch()
|
app_multi_tab.py
ADDED
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from prompts.system_prompts import get_systemprompt, system_prompt_templates
|
3 |
+
|
4 |
+
# Define some pre-written templates for Tab 1
|
5 |
+
templates = {
|
6 |
+
"Friendly Chatbot": "You are a helpful, friendly chatbot that engages in light-hearted conversations.",
|
7 |
+
"Technical Assistant": "You are a technical assistant specialized in answering questions related to Python programming.",
|
8 |
+
"Nutrition Advisor": "You provide evidence-based advice on nutrition and healthy eating habits.",
|
9 |
+
}
|
10 |
+
|
11 |
+
# Define some agentic workflows for Tab 2
|
12 |
+
agentic_workflows = {
|
13 |
+
"Blog Post Generator": "This agent is designed to help generate a blog post based on user input.",
|
14 |
+
"Document Summarizer": "This agent summarizes long documents by extracting key points.",
|
15 |
+
"Task Manager": "This agent helps you organize tasks and provides step-by-step guidance."
|
16 |
+
}
|
17 |
+
|
18 |
+
# Chatbot logic for custom instructions or pre-written templates
|
19 |
+
def chatbot_response(system_instructions, user_query):
|
20 |
+
if "friendly" in system_instructions.lower():
|
21 |
+
return f"Friendly Chatbot says: Hi there! 😊 How can I assist you today?"
|
22 |
+
elif "technical" in system_instructions.lower():
|
23 |
+
return f"Technical Assistant says: Sure! Here's some information on Python: {user_query}"
|
24 |
+
elif "nutrition" in system_instructions.lower():
|
25 |
+
return f"Nutrition Advisor says: Here's some advice about healthy eating: {user_query}"
|
26 |
+
else:
|
27 |
+
return f"Custom Chatbot says: {user_query}"
|
28 |
+
|
29 |
+
# Chatbot conversation function
|
30 |
+
def chatbot_conversation(system_instructions, chat_history, user_query):
|
31 |
+
response = chatbot_response(system_instructions, user_query)
|
32 |
+
chat_history.append((user_query, response))
|
33 |
+
return chat_history, ""
|
34 |
+
|
35 |
+
# Chatbot conversation for predefined agentic workflows
|
36 |
+
def agentic_chatbot_conversation(workflow_instructions, chat_history, user_query):
|
37 |
+
response = f"Agent Workflow ({workflow_instructions}) says: {user_query}"
|
38 |
+
chat_history.append((user_query, response))
|
39 |
+
return chat_history, ""
|
40 |
+
|
41 |
+
# Function to update the interface when a selection is made from the dropdown (Tab 1)
|
42 |
+
def update_interface(template_name, custom_instructions):
|
43 |
+
if template_name == "Custom Instructions":
|
44 |
+
return gr.update(visible=True), gr.update(visible=False)
|
45 |
+
else:
|
46 |
+
template_content = templates.get(template_name, "")
|
47 |
+
return gr.update(visible=False), gr.update(visible=True, value=template_content)
|
48 |
+
|
49 |
+
# Build the Gradio interface with Tabs
|
50 |
+
with gr.Blocks(css=".gradio-container {background-color: #F0F0F0;} .gr-button {background-color: #1E3A8A; color: white;} .gr-textbox textarea {font-size: 16px;} .gr-markdown {font-size: 18px; color: #1E3A8A;}") as demo:
|
51 |
+
|
52 |
+
# Add Tabs
|
53 |
+
with gr.Tabs():
|
54 |
+
|
55 |
+
# Tab 1: Custom Instructions or Pre-Written Templates
|
56 |
+
with gr.Tab("Custom Instructions Chatbot"):
|
57 |
+
gr.Markdown("""
|
58 |
+
<div style='background-color:#E0E0E0; padding: 20px; border-radius: 10px;'>
|
59 |
+
<h1 style='text-align: center; color: #1E3A8A;'>SRF Innovation Labs - AI Chatbot Use Case Explorer</h1>
|
60 |
+
<p style='font-size: 18px; text-align: center; color: #1E3A8A;'>
|
61 |
+
This tool allows you to experiment with different system prompts,
|
62 |
+
giving you control over how the chatbot behaves. You can either use pre-defined templates
|
63 |
+
or write your own custom instructions.
|
64 |
+
</p>
|
65 |
+
</div>
|
66 |
+
""")
|
67 |
+
|
68 |
+
# Section to select system instructions from dropdown
|
69 |
+
gr.Markdown("<h2 style='color: #1E3A8A;'>Chatbot Setup</h2>")
|
70 |
+
template_name = gr.Dropdown(choices=["Custom Instructions"] + list(templates.keys()), label="Choose Instructions", value="Friendly Chatbot")
|
71 |
+
custom_instructions = gr.Textbox(label="Custom Instructions", visible=False, placeholder="Write your own instructions here...")
|
72 |
+
template_display = gr.Textbox(label="Template Content", interactive=False, visible=True)
|
73 |
+
|
74 |
+
# Chatbot interface
|
75 |
+
gr.Markdown("<h2 style='color: #1E3A8A;'>Chatbot Interaction</h2>")
|
76 |
+
chatbot = gr.Chatbot(label="Chatbot Conversation", height=300, show_label=False)
|
77 |
+
user_query = gr.Textbox(label="Your Query", placeholder="Ask a question or say something to the chatbot...")
|
78 |
+
submit_button = gr.Button("Send", elem_classes=["gr-button"])
|
79 |
+
|
80 |
+
# Update logic for Tab 1
|
81 |
+
template_name.change(fn=update_interface, inputs=[template_name, custom_instructions], outputs=[custom_instructions, template_display])
|
82 |
+
submit_button.click(fn=chatbot_conversation, inputs=[custom_instructions if template_name == "Custom Instructions" else template_display, chatbot, user_query], outputs=[chatbot, user_query])
|
83 |
+
|
84 |
+
# Tab 2: Predefined Agentic Workflows
|
85 |
+
with gr.Tab("Agentic Workflow Chatbots"):
|
86 |
+
gr.Markdown("""
|
87 |
+
<div style='background-color:#E0E0E0; padding: 20px; border-radius: 10px;'>
|
88 |
+
<h1 style='text-align: center; color: #1E3A8A;'>Agentic Workflow Explorer</h1>
|
89 |
+
<p style='font-size: 18px; text-align: center; color: #1E3A8A;'>
|
90 |
+
Explore predefined agentic workflows that execute specific tasks, such as generating blog posts,
|
91 |
+
summarizing documents, or managing tasks.
|
92 |
+
</p>
|
93 |
+
</div>
|
94 |
+
""")
|
95 |
+
|
96 |
+
# Dropdown for selecting agentic workflows
|
97 |
+
workflow_name = gr.Dropdown(choices=list(agentic_workflows.keys()), label="Choose Agent Workflow", value="Blog Post Generator")
|
98 |
+
workflow_display = gr.Textbox(label="Workflow Description", interactive=False, visible=True)
|
99 |
+
workflow_chatbot = gr.Chatbot(label="Agent Workflow Conversation", height=300, show_label=False)
|
100 |
+
workflow_user_query = gr.Textbox(label="Your Query", placeholder="Ask the agent to perform a task...")
|
101 |
+
workflow_submit_button = gr.Button("Send", elem_classes=["gr-button"])
|
102 |
+
|
103 |
+
# Chatbot interaction for agentic workflows
|
104 |
+
workflow_submit_button.click(fn=agentic_chatbot_conversation, inputs=[workflow_name, workflow_chatbot, workflow_user_query], outputs=[workflow_chatbot, workflow_user_query])
|
105 |
+
|
106 |
+
# Launch the app
|
107 |
+
demo.launch()
|
notebooks/01 Basic Chatbot.ipynb
CHANGED
@@ -2,14 +2,16 @@
|
|
2 |
"cells": [
|
3 |
{
|
4 |
"cell_type": "code",
|
5 |
-
"execution_count":
|
6 |
"metadata": {},
|
7 |
"outputs": [
|
8 |
{
|
9 |
"name": "stdout",
|
10 |
"output_type": "stream",
|
11 |
"text": [
|
12 |
-
"
|
|
|
|
|
13 |
]
|
14 |
}
|
15 |
],
|
@@ -38,20 +40,8 @@
|
|
38 |
"%load_ext autoreload\n",
|
39 |
"%autoreload 2\n",
|
40 |
"\n",
|
41 |
-
"import src.qdrant_manager as qm\n",
|
42 |
"\n",
|
43 |
-
"# Check available kernels\n",
|
44 |
-
"from jupyter_client import kernelspec\n",
|
45 |
-
"print(\"Available kernels:\")\n",
|
46 |
-
"for kernel in kernelspec.find_kernel_specs():\n",
|
47 |
-
" print(kernel)\n",
|
48 |
-
"\n",
|
49 |
-
"# If you still can't see your kernel, you might need to restart your Jupyter environment\n",
|
50 |
-
"# or ensure that the kernel is properly installed and registered.\n",
|
51 |
-
"# You can also try running the following in a terminal:\n",
|
52 |
-
"# python -m ipykernel install --user --name=your_kernel_name\n",
|
53 |
-
"\n",
|
54 |
-
"# If issues persist, check your Jupyter configuration and environment setup.\n",
|
55 |
"\n",
|
56 |
"\n"
|
57 |
]
|
@@ -166,14 +156,14 @@
|
|
166 |
},
|
167 |
{
|
168 |
"cell_type": "code",
|
169 |
-
"execution_count":
|
170 |
"metadata": {},
|
171 |
"outputs": [
|
172 |
{
|
173 |
"name": "stderr",
|
174 |
"output_type": "stream",
|
175 |
"text": [
|
176 |
-
"/Users/nadaa/Documents/code/
|
177 |
" self.qdrant = Qdrant(\n"
|
178 |
]
|
179 |
},
|
@@ -322,7 +312,7 @@
|
|
322 |
},
|
323 |
{
|
324 |
"cell_type": "code",
|
325 |
-
"execution_count":
|
326 |
"metadata": {},
|
327 |
"outputs": [],
|
328 |
"source": [
|
@@ -332,26 +322,34 @@
|
|
332 |
},
|
333 |
{
|
334 |
"cell_type": "code",
|
335 |
-
"execution_count":
|
336 |
"metadata": {},
|
337 |
"outputs": [
|
338 |
{
|
339 |
"name": "stdout",
|
340 |
"output_type": "stream",
|
341 |
"text": [
|
342 |
-
"Here are the full passages
|
|
|
|
|
343 |
"\n",
|
344 |
-
"
|
345 |
"\n",
|
346 |
-
"
|
347 |
"\n",
|
348 |
-
"
|
349 |
"\n",
|
350 |
-
"
|
351 |
"\n",
|
352 |
-
"
|
|
|
|
|
|
|
353 |
"\n",
|
354 |
-
"
|
|
|
|
|
|
|
355 |
]
|
356 |
}
|
357 |
],
|
@@ -581,9 +579,9 @@
|
|
581 |
],
|
582 |
"metadata": {
|
583 |
"kernelspec": {
|
584 |
-
"display_name": "
|
585 |
"language": "python",
|
586 |
-
"name": "
|
587 |
},
|
588 |
"language_info": {
|
589 |
"codemirror_mode": {
|
|
|
2 |
"cells": [
|
3 |
{
|
4 |
"cell_type": "code",
|
5 |
+
"execution_count": 8,
|
6 |
"metadata": {},
|
7 |
"outputs": [
|
8 |
{
|
9 |
"name": "stdout",
|
10 |
"output_type": "stream",
|
11 |
"text": [
|
12 |
+
"srf-chatbot\n",
|
13 |
+
"The autoreload extension is already loaded. To reload it, use:\n",
|
14 |
+
" %reload_ext autoreload\n"
|
15 |
]
|
16 |
}
|
17 |
],
|
|
|
40 |
"%load_ext autoreload\n",
|
41 |
"%autoreload 2\n",
|
42 |
"\n",
|
43 |
+
"import src.utils.qdrant_manager as qm\n",
|
44 |
"\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
"\n",
|
46 |
"\n"
|
47 |
]
|
|
|
156 |
},
|
157 |
{
|
158 |
"cell_type": "code",
|
159 |
+
"execution_count": 9,
|
160 |
"metadata": {},
|
161 |
"outputs": [
|
162 |
{
|
163 |
"name": "stderr",
|
164 |
"output_type": "stream",
|
165 |
"text": [
|
166 |
+
"/Users/nadaa/Documents/code/py_innovations/srf_chatbot_v2/src/utils/qdrant_manager.py:51: LangChainDeprecationWarning: The class `Qdrant` was deprecated in LangChain 0.1.2 and will be removed in 0.5.0. Use :class:`~QdrantVectorStore` instead.\n",
|
167 |
" self.qdrant = Qdrant(\n"
|
168 |
]
|
169 |
},
|
|
|
312 |
},
|
313 |
{
|
314 |
"cell_type": "code",
|
315 |
+
"execution_count": 10,
|
316 |
"metadata": {},
|
317 |
"outputs": [],
|
318 |
"source": [
|
|
|
322 |
},
|
323 |
{
|
324 |
"cell_type": "code",
|
325 |
+
"execution_count": 11,
|
326 |
"metadata": {},
|
327 |
"outputs": [
|
328 |
{
|
329 |
"name": "stdout",
|
330 |
"output_type": "stream",
|
331 |
"text": [
|
332 |
+
"Here are the full passages from the teachings of Paramhansa Yogananda regarding the importance of a true guru, with key quotes emphasized:\n",
|
333 |
+
"\n",
|
334 |
+
"1. **\"It is admirable to lecture and teach good principles; but without possessing the qualifications of a real guru a teacher cannot redeem souls, nor should he presume to accept others as disciples until he himself has progressed far in his own Self-realization.\"** True gurus train first their inner selves in the theologically advanced school of intuition and God-communion in meditation. They spiritually baptize themselves in Spirit before they aspire to initiate others. They teach not for mundane gain or glory, but for the singular purpose of leading souls to God. A guru never seeks for himself the devotion and obedience of his disciples, but transfers that reverence to God. It is not necessary for a disciple to be in the company of the guru in order to receive his blessings. What is most important is to be spiritually in tune with the guru, for his help is transferred to the disciple primarily on the inner spiritual plane rather than through material means.\n",
|
335 |
"\n",
|
336 |
+
"2. **\"A guru is not an ordinary spiritual teacher.\"** One may have many teachers, but only one guru, who is the agent of salvation appointed by God in response to a devotee’s demands for release from the bondage of matter. Ministers in churches and priests in temples are oftentimes chosen only by a set standard of their intellectual knowledge of the scriptures, or by virtue of sacerdotal authority ceremonially conferred on them by a formally higher ecclesiastical superior. No guru can be developed only by years of study in the intellectual factory of a theological seminary, which deems it has attained its ends when it confers B.D. or D.D. degrees. Such titles can be won by men of good memory; but character, self-control, and the wisdom of soul intuition can be cultured only by knowledge and application of advanced methods of deep daily meditation that produce Self-realization and actual experience of God.\n",
|
337 |
"\n",
|
338 |
+
"3. **\"Discretion and caution are particularly necessary in accepting a guru.\"** One may have many teachers in the beginning of his search, but when one’s heart and soul are confidently settled in a guru-disciple relationship ordained and blessed by God, the disciple has only one guru, and no other teachers thereafter. The devotee remains loyal to such a guru, being spiritually fulfilled by the God-sent messenger. To forsake the guru and his ideals is to spurn the help sent by God, the One Guru of gurus. **\"Unconditional love, loyalty, and obedience are hallmarks of the guru-disciple relationship.\"** The spiritual soul contact between guru and disciple is one of eternal, unconditional divine love and friendship, bearing no taint of any selfish consideration.\n",
|
339 |
"\n",
|
340 |
+
"4. **\"Of the total requirement to achieve salvation, it is said that 25% is the disciple’s spiritual effort, 25% is the blessing of the guru, and the remaining 50% is the grace of God.\"** The aspirant should not be tempted into complacency, however, waiting to be moved by the spirit of the blessings and grace, for it is the catalyst of the devotee’s effort that makes the formula work. As the devotee’s effort and the guru’s blessings are equally necessary to the disciple’s progress, we are taught in India the first requisite importance on the spiritual path of following faithfully one’s guru.\n",
|
341 |
"\n",
|
342 |
+
"5. **\"What is most important is to be spiritually in tune with the guru.\"** If the disciple is uncarping, unconditionally reverential and loving to the master, and faithful in following his precepts, his receptivity makes the task of the guru easier. Attunement links the help of the guru with the sincere striving of the disciple, even if the guru is no longer incarnate on earth.\n",
|
343 |
"\n",
|
344 |
+
"### Recommended Reading:\n",
|
345 |
+
"- \"The Second Coming of Christ\" by Paramhansa Yogananda\n",
|
346 |
+
"- \"Autobiography of a Yogi\" by Paramhansa Yogananda\n",
|
347 |
+
"- \"The Yoga of Jesus\" by Paramhansa Yogananda\n",
|
348 |
"\n",
|
349 |
+
"### Follow-Up Questions:\n",
|
350 |
+
"1. What qualities should one look for in a true guru?\n",
|
351 |
+
"2. How can a disciple cultivate a deeper connection with their guru?\n",
|
352 |
+
"3. Can the teachings of a guru be accessed without physical presence?\n"
|
353 |
]
|
354 |
}
|
355 |
],
|
|
|
579 |
],
|
580 |
"metadata": {
|
581 |
"kernelspec": {
|
582 |
+
"display_name": "srf_chatbot_v2",
|
583 |
"language": "python",
|
584 |
+
"name": "srf_chatbot_v2"
|
585 |
},
|
586 |
"language_info": {
|
587 |
"codemirror_mode": {
|
notebooks/02 Chatbot with custom system prompt.ipynb
CHANGED
@@ -0,0 +1,287 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"cells": [
|
3 |
+
{
|
4 |
+
"cell_type": "code",
|
5 |
+
"execution_count": 5,
|
6 |
+
"metadata": {},
|
7 |
+
"outputs": [
|
8 |
+
{
|
9 |
+
"name": "stdout",
|
10 |
+
"output_type": "stream",
|
11 |
+
"text": [
|
12 |
+
"Running on local URL: http://127.0.0.1:7864\n",
|
13 |
+
"\n",
|
14 |
+
"To create a public link, set `share=True` in `launch()`.\n"
|
15 |
+
]
|
16 |
+
},
|
17 |
+
{
|
18 |
+
"data": {
|
19 |
+
"text/html": [
|
20 |
+
"<div><iframe src=\"http://127.0.0.1:7864/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
|
21 |
+
],
|
22 |
+
"text/plain": [
|
23 |
+
"<IPython.core.display.HTML object>"
|
24 |
+
]
|
25 |
+
},
|
26 |
+
"metadata": {},
|
27 |
+
"output_type": "display_data"
|
28 |
+
},
|
29 |
+
{
|
30 |
+
"data": {
|
31 |
+
"text/plain": []
|
32 |
+
},
|
33 |
+
"execution_count": 5,
|
34 |
+
"metadata": {},
|
35 |
+
"output_type": "execute_result"
|
36 |
+
}
|
37 |
+
],
|
38 |
+
"source": [
|
39 |
+
"import gradio as gr\n",
|
40 |
+
"\n",
|
41 |
+
"# Define some pre-written templates\n",
|
42 |
+
"templates = {\n",
|
43 |
+
" \"Friendly Chatbot\": \"You are a helpful, friendly chatbot that engages in light-hearted conversations.\",\n",
|
44 |
+
" \"Technical Assistant\": \"You are a technical assistant specialized in answering questions related to Python programming.\",\n",
|
45 |
+
" \"Nutrition Advisor\": \"You provide evidence-based advice on nutrition and healthy eating habits.\",\n",
|
46 |
+
"}\n",
|
47 |
+
"\n",
|
48 |
+
"# Chatbot logic: Takes system instructions and user query, returns a response\n",
|
49 |
+
"def chatbot_response(system_instructions, user_query):\n",
|
50 |
+
" if \"friendly\" in system_instructions.lower():\n",
|
51 |
+
" return f\"Friendly Chatbot says: Hi there! 😊 How can I assist you today?\"\n",
|
52 |
+
" elif \"technical\" in system_instructions.lower():\n",
|
53 |
+
" return f\"Technical Assistant says: Sure! Here's some information on Python: {user_query}\"\n",
|
54 |
+
" elif \"nutrition\" in system_instructions.lower():\n",
|
55 |
+
" return f\"Nutrition Advisor says: Here's some advice about healthy eating: {user_query}\"\n",
|
56 |
+
" else:\n",
|
57 |
+
" return f\"Custom Chatbot says: {user_query}\"\n",
|
58 |
+
"\n",
|
59 |
+
"# Function to update the interface when a selection is made from the dropdown\n",
|
60 |
+
"def update_interface(template_name, custom_instructions):\n",
|
61 |
+
" if template_name == \"Custom Instructions\":\n",
|
62 |
+
" return gr.update(visible=True), gr.update(visible(False))\n",
|
63 |
+
" else:\n",
|
64 |
+
" template_content = templates.get(template_name, \"\")\n",
|
65 |
+
" return gr.update(visible=False), gr.update(visible=True, value=template_content)\n",
|
66 |
+
"\n",
|
67 |
+
"# Chatbot conversation function\n",
|
68 |
+
"def chatbot_conversation(system_instructions, chat_history, user_query):\n",
|
69 |
+
" response = chatbot_response(system_instructions, user_query)\n",
|
70 |
+
" chat_history.append((user_query, response))\n",
|
71 |
+
" return chat_history, \"\"\n",
|
72 |
+
"\n",
|
73 |
+
"# Build the Gradio interface\n",
|
74 |
+
"with gr.Blocks() as demo:\n",
|
75 |
+
" \n",
|
76 |
+
" # Add the title and description\n",
|
77 |
+
" gr.Markdown(\"# **SRF Innovation Labs - AI Chatbot Use Case Explorer**\")\n",
|
78 |
+
" gr.Markdown(\"\"\"\n",
|
79 |
+
" Welcome to the SRF Innovation Labs AI Chatbot Use Case Explorer! \n",
|
80 |
+
" This tool allows you to experiment with different system prompts, \n",
|
81 |
+
" giving you control over how the chatbot behaves. You can either use pre-defined templates or write your own custom instructions.\n",
|
82 |
+
" \n",
|
83 |
+
" Additionally, the chatbot has access to a vector database where it can look up and retrieve learnings for various queries. \n",
|
84 |
+
" This makes it an excellent platform for exploring potential AI use cases in real-time.\n",
|
85 |
+
" \"\"\")\n",
|
86 |
+
"\n",
|
87 |
+
" # Section to select system instructions from dropdown\n",
|
88 |
+
" gr.Markdown(\"## **Chatbot Setup**\")\n",
|
89 |
+
"\n",
|
90 |
+
" # Dropdown for selecting a pre-written template or custom instructions\n",
|
91 |
+
" template_name = gr.Dropdown(choices=[\"Custom Instructions\"] + list(templates.keys()), label=\"Choose Instructions\", value=\"Friendly Chatbot\")\n",
|
92 |
+
" \n",
|
93 |
+
" # Textbox for custom chatbot instructions (only shown when \"Custom Instructions\" is selected)\n",
|
94 |
+
" custom_instructions = gr.Textbox(label=\"Custom Instructions\", visible=False, placeholder=\"Write your own instructions here...\")\n",
|
95 |
+
" \n",
|
96 |
+
" # Output field to display the selected pre-written template (not shown when Custom Instructions is selected)\n",
|
97 |
+
" template_display = gr.Textbox(label=\"Template Content\", interactive=False, visible=True)\n",
|
98 |
+
" \n",
|
99 |
+
" # Section for chat interface\n",
|
100 |
+
" gr.Markdown(\"## **Chatbot Interaction**\")\n",
|
101 |
+
"\n",
|
102 |
+
" # Chatbot interface with chat history\n",
|
103 |
+
" chatbot = gr.Chatbot(label=\"Chatbot Conversation\")\n",
|
104 |
+
" user_query = gr.Textbox(label=\"Your Query\", placeholder=\"Ask a question or say something to the chatbot...\")\n",
|
105 |
+
"\n",
|
106 |
+
" # Button to submit the query\n",
|
107 |
+
" submit_button = gr.Button(\"Send\")\n",
|
108 |
+
"\n",
|
109 |
+
" # Update logic to control the display based on the dropdown selection\n",
|
110 |
+
" template_name.change(fn=update_interface, \n",
|
111 |
+
" inputs=[template_name, custom_instructions], \n",
|
112 |
+
" outputs=[custom_instructions, template_display])\n",
|
113 |
+
"\n",
|
114 |
+
" # Chatbot interaction logic\n",
|
115 |
+
" submit_button.click(fn=chatbot_conversation, \n",
|
116 |
+
" inputs=[custom_instructions if template_name == \"Custom Instructions\" else template_display, chatbot, user_query], \n",
|
117 |
+
" outputs=[chatbot, user_query])\n",
|
118 |
+
"\n",
|
119 |
+
"# Launch the app\n",
|
120 |
+
"demo.launch()\n"
|
121 |
+
]
|
122 |
+
},
|
123 |
+
{
|
124 |
+
"cell_type": "code",
|
125 |
+
"execution_count": 6,
|
126 |
+
"metadata": {},
|
127 |
+
"outputs": [
|
128 |
+
{
|
129 |
+
"name": "stdout",
|
130 |
+
"output_type": "stream",
|
131 |
+
"text": [
|
132 |
+
"Running on local URL: http://127.0.0.1:7865\n",
|
133 |
+
"\n",
|
134 |
+
"To create a public link, set `share=True` in `launch()`.\n"
|
135 |
+
]
|
136 |
+
},
|
137 |
+
{
|
138 |
+
"data": {
|
139 |
+
"text/html": [
|
140 |
+
"<div><iframe src=\"http://127.0.0.1:7865/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
|
141 |
+
],
|
142 |
+
"text/plain": [
|
143 |
+
"<IPython.core.display.HTML object>"
|
144 |
+
]
|
145 |
+
},
|
146 |
+
"metadata": {},
|
147 |
+
"output_type": "display_data"
|
148 |
+
},
|
149 |
+
{
|
150 |
+
"data": {
|
151 |
+
"text/plain": []
|
152 |
+
},
|
153 |
+
"execution_count": 6,
|
154 |
+
"metadata": {},
|
155 |
+
"output_type": "execute_result"
|
156 |
+
}
|
157 |
+
],
|
158 |
+
"source": [
|
159 |
+
"import gradio as gr\n",
|
160 |
+
"\n",
|
161 |
+
"# Define some pre-written templates for Tab 1\n",
|
162 |
+
"templates = {\n",
|
163 |
+
" \"Friendly Chatbot\": \"You are a helpful, friendly chatbot that engages in light-hearted conversations.\",\n",
|
164 |
+
" \"Technical Assistant\": \"You are a technical assistant specialized in answering questions related to Python programming.\",\n",
|
165 |
+
" \"Nutrition Advisor\": \"You provide evidence-based advice on nutrition and healthy eating habits.\",\n",
|
166 |
+
"}\n",
|
167 |
+
"\n",
|
168 |
+
"# Define some agentic workflows for Tab 2\n",
|
169 |
+
"agentic_workflows = {\n",
|
170 |
+
" \"Blog Post Generator\": \"This agent is designed to help generate a blog post based on user input.\",\n",
|
171 |
+
" \"Document Summarizer\": \"This agent summarizes long documents by extracting key points.\",\n",
|
172 |
+
" \"Task Manager\": \"This agent helps you organize tasks and provides step-by-step guidance.\"\n",
|
173 |
+
"}\n",
|
174 |
+
"\n",
|
175 |
+
"# Chatbot logic for custom instructions or pre-written templates\n",
|
176 |
+
"def chatbot_response(system_instructions, user_query):\n",
|
177 |
+
" if \"friendly\" in system_instructions.lower():\n",
|
178 |
+
" return f\"Friendly Chatbot says: Hi there! 😊 How can I assist you today?\"\n",
|
179 |
+
" elif \"technical\" in system_instructions.lower():\n",
|
180 |
+
" return f\"Technical Assistant says: Sure! Here's some information on Python: {user_query}\"\n",
|
181 |
+
" elif \"nutrition\" in system_instructions.lower():\n",
|
182 |
+
" return f\"Nutrition Advisor says: Here's some advice about healthy eating: {user_query}\"\n",
|
183 |
+
" else:\n",
|
184 |
+
" return f\"Custom Chatbot says: {user_query}\"\n",
|
185 |
+
"\n",
|
186 |
+
"# Chatbot conversation function\n",
|
187 |
+
"def chatbot_conversation(system_instructions, chat_history, user_query):\n",
|
188 |
+
" response = chatbot_response(system_instructions, user_query)\n",
|
189 |
+
" chat_history.append((user_query, response))\n",
|
190 |
+
" return chat_history, \"\"\n",
|
191 |
+
"\n",
|
192 |
+
"# Chatbot conversation for predefined agentic workflows\n",
|
193 |
+
"def agentic_chatbot_conversation(workflow_instructions, chat_history, user_query):\n",
|
194 |
+
" response = f\"Agent Workflow ({workflow_instructions}) says: {user_query}\"\n",
|
195 |
+
" chat_history.append((user_query, response))\n",
|
196 |
+
" return chat_history, \"\"\n",
|
197 |
+
"\n",
|
198 |
+
"# Function to update the interface when a selection is made from the dropdown (Tab 1)\n",
|
199 |
+
"def update_interface(template_name, custom_instructions):\n",
|
200 |
+
" if template_name == \"Custom Instructions\":\n",
|
201 |
+
" return gr.update(visible=True), gr.update(visible=False)\n",
|
202 |
+
" else:\n",
|
203 |
+
" template_content = templates.get(template_name, \"\")\n",
|
204 |
+
" return gr.update(visible=False), gr.update(visible=True, value=template_content)\n",
|
205 |
+
"\n",
|
206 |
+
"# Build the Gradio interface with Tabs\n",
|
207 |
+
"with gr.Blocks() as demo:\n",
|
208 |
+
" \n",
|
209 |
+
" # Add Tabs\n",
|
210 |
+
" with gr.Tabs():\n",
|
211 |
+
" \n",
|
212 |
+
" # Tab 1: Custom Instructions or Pre-Written Templates\n",
|
213 |
+
" with gr.Tab(\"Custom Instructions Chatbot\"):\n",
|
214 |
+
" gr.Markdown(\"# **SRF Innovation Labs - AI Chatbot Use Case Explorer**\")\n",
|
215 |
+
" gr.Markdown(\"\"\"\n",
|
216 |
+
" This tool allows you to experiment with different system prompts, \n",
|
217 |
+
" giving you control over how the chatbot behaves. You can either use pre-defined templates or write your own custom instructions.\n",
|
218 |
+
" \"\"\")\n",
|
219 |
+
"\n",
|
220 |
+
" # Section to select system instructions from dropdown\n",
|
221 |
+
" gr.Markdown(\"## **Chatbot Setup**\")\n",
|
222 |
+
" template_name = gr.Dropdown(choices=[\"Custom Instructions\"] + list(templates.keys()), label=\"Choose Instructions\", value=\"Friendly Chatbot\")\n",
|
223 |
+
" custom_instructions = gr.Textbox(label=\"Custom Instructions\", visible=False, placeholder=\"Write your own instructions here...\")\n",
|
224 |
+
" template_display = gr.Textbox(label=\"Template Content\", interactive=False, visible=True)\n",
|
225 |
+
"\n",
|
226 |
+
" # Chatbot interface\n",
|
227 |
+
" gr.Markdown(\"## **Chatbot Interaction**\")\n",
|
228 |
+
" chatbot = gr.Chatbot(label=\"Chatbot Conversation\")\n",
|
229 |
+
" user_query = gr.Textbox(label=\"Your Query\", placeholder=\"Ask a question or say something to the chatbot...\")\n",
|
230 |
+
" submit_button = gr.Button(\"Send\")\n",
|
231 |
+
"\n",
|
232 |
+
" # Update logic for Tab 1\n",
|
233 |
+
" template_name.change(fn=update_interface, inputs=[template_name, custom_instructions], outputs=[custom_instructions, template_display])\n",
|
234 |
+
" submit_button.click(fn=chatbot_conversation, inputs=[custom_instructions if template_name == \"Custom Instructions\" else template_display, chatbot, user_query], outputs=[chatbot, user_query])\n",
|
235 |
+
"\n",
|
236 |
+
" # Tab 2: Predefined Agentic Workflows\n",
|
237 |
+
" with gr.Tab(\"Agentic Workflow Chatbots\"):\n",
|
238 |
+
" gr.Markdown(\"# **Agentic Workflow Explorer**\")\n",
|
239 |
+
" gr.Markdown(\"\"\"\n",
|
240 |
+
" This tab allows you to experiment with different agentic workflows that are predefined. \n",
|
241 |
+
" Each workflow executes a specific task, such as generating blog posts, summarizing documents, or managing tasks.\n",
|
242 |
+
" \"\"\")\n",
|
243 |
+
"\n",
|
244 |
+
" # Dropdown for selecting agentic workflows\n",
|
245 |
+
" workflow_name = gr.Dropdown(choices=list(agentic_workflows.keys()), label=\"Choose Agent Workflow\", value=\"Blog Post Generator\")\n",
|
246 |
+
" workflow_display = gr.Textbox(label=\"Workflow Description\", interactive=False, visible=True)\n",
|
247 |
+
" workflow_chatbot = gr.Chatbot(label=\"Agent Workflow Conversation\")\n",
|
248 |
+
" workflow_user_query = gr.Textbox(label=\"Your Query\", placeholder=\"Ask the agent to perform a task...\")\n",
|
249 |
+
" workflow_submit_button = gr.Button(\"Send\")\n",
|
250 |
+
"\n",
|
251 |
+
" # Chatbot interaction for agentic workflows\n",
|
252 |
+
" workflow_submit_button.click(fn=agentic_chatbot_conversation, inputs=[workflow_name, workflow_chatbot, workflow_user_query], outputs=[workflow_chatbot, workflow_user_query])\n",
|
253 |
+
"\n",
|
254 |
+
"# Launch the app\n",
|
255 |
+
"demo.launch()\n"
|
256 |
+
]
|
257 |
+
},
|
258 |
+
{
|
259 |
+
"cell_type": "code",
|
260 |
+
"execution_count": null,
|
261 |
+
"metadata": {},
|
262 |
+
"outputs": [],
|
263 |
+
"source": []
|
264 |
+
}
|
265 |
+
],
|
266 |
+
"metadata": {
|
267 |
+
"kernelspec": {
|
268 |
+
"display_name": "srf_chatbot_v2",
|
269 |
+
"language": "python",
|
270 |
+
"name": "srf_chatbot_v2"
|
271 |
+
},
|
272 |
+
"language_info": {
|
273 |
+
"codemirror_mode": {
|
274 |
+
"name": "ipython",
|
275 |
+
"version": 3
|
276 |
+
},
|
277 |
+
"file_extension": ".py",
|
278 |
+
"mimetype": "text/x-python",
|
279 |
+
"name": "python",
|
280 |
+
"nbconvert_exporter": "python",
|
281 |
+
"pygments_lexer": "ipython3",
|
282 |
+
"version": "3.11.9"
|
283 |
+
}
|
284 |
+
},
|
285 |
+
"nbformat": 4,
|
286 |
+
"nbformat_minor": 2
|
287 |
+
}
|
notebooks/03 Experimentation Chatbot.ipynb
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
"cells": [
|
3 |
{
|
4 |
"cell_type": "code",
|
5 |
-
"execution_count":
|
6 |
"metadata": {},
|
7 |
"outputs": [
|
8 |
{
|
@@ -51,7 +51,7 @@
|
|
51 |
},
|
52 |
{
|
53 |
"cell_type": "code",
|
54 |
-
"execution_count":
|
55 |
"metadata": {},
|
56 |
"outputs": [],
|
57 |
"source": [
|
@@ -93,20 +93,15 @@
|
|
93 |
},
|
94 |
{
|
95 |
"cell_type": "code",
|
96 |
-
"execution_count":
|
97 |
"metadata": {},
|
98 |
"outputs": [],
|
99 |
"source": [
|
100 |
-
"# class ChatbotState(TypedDict):\n",
|
101 |
-
"# # Messages have the type \"list\". The `add_messages` function defines how this state key should be updated\n",
|
102 |
-
"# # (in this case, it appends messages to the list, rather than overwriting them)\n",
|
103 |
-
"# messages: Annotated[list, add_messages]\n",
|
104 |
-
"\n",
|
105 |
"\n",
|
106 |
"class SRFChatbot:\n",
|
107 |
" def __init__(\n",
|
108 |
" self,\n",
|
109 |
-
" chatbot_instructions: str,\n",
|
110 |
" model: str = 'gpt-4o-mini',\n",
|
111 |
" temperature: float = 0,\n",
|
112 |
" ):\n",
|
@@ -121,8 +116,18 @@
|
|
121 |
" # Get the configurable\n",
|
122 |
" self.config = self.get_configurable()\n",
|
123 |
" \n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
124 |
"\n",
|
125 |
" def get_configurable(self):\n",
|
|
|
126 |
" self.thread_id = str(uuid.uuid4())\n",
|
127 |
" return {\"configurable\": {\"thread_id\": self.thread_id}}\n",
|
128 |
" \n",
|
@@ -164,104 +169,202 @@
|
|
164 |
},
|
165 |
{
|
166 |
"cell_type": "code",
|
167 |
-
"execution_count":
|
168 |
"metadata": {},
|
169 |
"outputs": [],
|
170 |
"source": [
|
171 |
-
"
|
172 |
-
"chatbot = SRFChatbot(chatbot_instructions=chatbot_instructions)\n"
|
173 |
]
|
174 |
},
|
175 |
{
|
176 |
"cell_type": "code",
|
177 |
-
"execution_count":
|
178 |
"metadata": {},
|
179 |
"outputs": [],
|
180 |
"source": [
|
181 |
-
"query = \"
|
182 |
"results = chatbot.graph.invoke({\"messages\": [HumanMessage(content=query)]}, chatbot.config)"
|
183 |
]
|
184 |
},
|
185 |
{
|
186 |
"cell_type": "code",
|
187 |
-
"execution_count":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
188 |
"metadata": {},
|
189 |
"outputs": [
|
190 |
{
|
191 |
"data": {
|
192 |
"text/plain": [
|
193 |
-
"[HumanMessage(content='
|
194 |
-
" AIMessage(content='', additional_kwargs={'tool_calls': [{'id': '
|
195 |
-
" ToolMessage(content=\"[Document(metadata={'chapter_name': '
|
196 |
-
" AIMessage(content
|
197 |
]
|
198 |
},
|
199 |
-
"execution_count":
|
200 |
"metadata": {},
|
201 |
"output_type": "execute_result"
|
202 |
}
|
203 |
],
|
204 |
"source": [
|
205 |
-
"
|
|
|
206 |
]
|
207 |
},
|
208 |
{
|
209 |
"cell_type": "code",
|
210 |
-
"execution_count":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
211 |
"metadata": {},
|
212 |
"outputs": [
|
213 |
{
|
214 |
"name": "stdout",
|
215 |
"output_type": "stream",
|
216 |
"text": [
|
217 |
-
"
|
218 |
-
"\n",
|
219 |
-
"1. **Understanding Sleep**: Sleep is described as an unconscious way of turning off life energy from the nerves. While you get some rest during sleep, it does not provide the conscious experience of bliss that meditation can offer. By practicing meditation and striving to reach a superconscious state, you can experience lasting spiritual changes and a deeper sense of joy that can accompany you even during your waking hours.\n",
|
220 |
-
"\n",
|
221 |
-
"2. **Conscious Withdrawal**: Yogananda explains that the yogi learns to consciously withdraw from sensory nerves, allowing for a peaceful state of meditation. This practice can help you manage disturbances that might affect your sleep. By training yourself to switch off the senses at will, you can go beyond mere subconscious slumber into a blissful state of interiorization.\n",
|
222 |
-
"\n",
|
223 |
-
"3. **The Nature of Sleep**: Sleep serves as a reminder of the soul's existence beyond the physical body. It allows for a temporary escape from physical limitations. Engaging in practices like Kriya Yoga meditation can help you connect with your soul and experience a sense of freedom and bliss, even during the day.\n",
|
224 |
-
"\n",
|
225 |
-
"4. **Managing Nervousness**: Nervousness can significantly impact your ability to sleep. Yogananda advises avoiding undue excitement, restlessness, and sudden emotions, as these can burn up the nervous system. Creating a peaceful environment, minimizing noise, and enjoying silence can help calm your nerves and improve your sleep quality.\n",
|
226 |
"\n",
|
227 |
-
"
|
228 |
-
"\n",
|
229 |
-
"Consider integrating these practices into your life to help improve your sleep quality.\n"
|
230 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
231 |
}
|
232 |
],
|
233 |
"source": [
|
234 |
-
"
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
"\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
244 |
]
|
245 |
},
|
246 |
{
|
247 |
"cell_type": "code",
|
248 |
-
"execution_count":
|
249 |
"metadata": {},
|
250 |
"outputs": [
|
251 |
{
|
252 |
"name": "stdout",
|
253 |
"output_type": "stream",
|
254 |
"text": [
|
255 |
-
"Running on local URL: http://127.0.0.1:
|
256 |
-
"Running on public URL: https://94b754ba708e7402d2.gradio.live\n",
|
257 |
"\n",
|
258 |
-
"
|
259 |
]
|
260 |
},
|
261 |
{
|
262 |
"data": {
|
263 |
"text/html": [
|
264 |
-
"<div><iframe src=\"
|
265 |
],
|
266 |
"text/plain": [
|
267 |
"<IPython.core.display.HTML object>"
|
@@ -274,46 +377,143 @@
|
|
274 |
"data": {
|
275 |
"text/plain": []
|
276 |
},
|
277 |
-
"execution_count":
|
278 |
"metadata": {},
|
279 |
"output_type": "execute_result"
|
280 |
}
|
281 |
],
|
282 |
"source": [
|
283 |
-
"
|
284 |
-
"
|
285 |
-
"
|
286 |
-
"
|
287 |
-
"
|
288 |
-
" if ai: # AI might not have responded yet\n",
|
289 |
-
" formatted_messages.append(AIMessage(content=ai))\n",
|
290 |
-
" \n",
|
291 |
-
" # Add the new message\n",
|
292 |
-
" formatted_messages.append(HumanMessage(content=message))\n",
|
293 |
-
" \n",
|
294 |
" # Invoke the graph with properly formatted input\n",
|
295 |
-
" result = chatbot.graph.invoke({\"messages\":
|
296 |
" \n",
|
297 |
" # Extract the assistant's response\n",
|
298 |
" response = result[\"messages\"][-1].content\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
299 |
" \n",
|
300 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
301 |
"\n",
|
302 |
-
"#
|
303 |
-
"
|
304 |
-
"gradio.launch(share=True)"
|
305 |
]
|
306 |
},
|
307 |
{
|
308 |
"cell_type": "code",
|
309 |
-
"execution_count":
|
310 |
"metadata": {},
|
311 |
"outputs": [
|
312 |
{
|
313 |
"name": "stdout",
|
314 |
"output_type": "stream",
|
315 |
"text": [
|
316 |
-
"Running on local URL: http://127.0.0.1:
|
317 |
"\n",
|
318 |
"To create a public link, set `share=True` in `launch()`.\n"
|
319 |
]
|
@@ -321,7 +521,7 @@
|
|
321 |
{
|
322 |
"data": {
|
323 |
"text/html": [
|
324 |
-
"<div><iframe src=\"http://127.0.0.1:
|
325 |
],
|
326 |
"text/plain": [
|
327 |
"<IPython.core.display.HTML object>"
|
@@ -334,118 +534,135 @@
|
|
334 |
"data": {
|
335 |
"text/plain": []
|
336 |
},
|
337 |
-
"execution_count":
|
338 |
"metadata": {},
|
339 |
"output_type": "execute_result"
|
340 |
-
},
|
341 |
-
{
|
342 |
-
"name": "stderr",
|
343 |
-
"output_type": "stream",
|
344 |
-
"text": [
|
345 |
-
"Traceback (most recent call last):\n",
|
346 |
-
" File \"/Users/nadaa/.local/share/virtualenvs/srf_chatbot_v2-9vTIDuJW/lib/python3.11/site-packages/gradio/queueing.py\", line 536, in process_events\n",
|
347 |
-
" response = await route_utils.call_process_api(\n",
|
348 |
-
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
|
349 |
-
" File \"/Users/nadaa/.local/share/virtualenvs/srf_chatbot_v2-9vTIDuJW/lib/python3.11/site-packages/gradio/route_utils.py\", line 322, in call_process_api\n",
|
350 |
-
" output = await app.get_blocks().process_api(\n",
|
351 |
-
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
|
352 |
-
" File \"/Users/nadaa/.local/share/virtualenvs/srf_chatbot_v2-9vTIDuJW/lib/python3.11/site-packages/gradio/blocks.py\", line 1935, in process_api\n",
|
353 |
-
" result = await self.call_function(\n",
|
354 |
-
" ^^^^^^^^^^^^^^^^^^^^^^^^^\n",
|
355 |
-
" File \"/Users/nadaa/.local/share/virtualenvs/srf_chatbot_v2-9vTIDuJW/lib/python3.11/site-packages/gradio/blocks.py\", line 1520, in call_function\n",
|
356 |
-
" prediction = await anyio.to_thread.run_sync( # type: ignore\n",
|
357 |
-
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
|
358 |
-
" File \"/Users/nadaa/.local/share/virtualenvs/srf_chatbot_v2-9vTIDuJW/lib/python3.11/site-packages/anyio/to_thread.py\", line 56, in run_sync\n",
|
359 |
-
" return await get_async_backend().run_sync_in_worker_thread(\n",
|
360 |
-
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
|
361 |
-
" File \"/Users/nadaa/.local/share/virtualenvs/srf_chatbot_v2-9vTIDuJW/lib/python3.11/site-packages/anyio/_backends/_asyncio.py\", line 2405, in run_sync_in_worker_thread\n",
|
362 |
-
" return await future\n",
|
363 |
-
" ^^^^^^^^^^^^\n",
|
364 |
-
" File \"/Users/nadaa/.local/share/virtualenvs/srf_chatbot_v2-9vTIDuJW/lib/python3.11/site-packages/anyio/_backends/_asyncio.py\", line 914, in run\n",
|
365 |
-
" result = context.run(func, *args)\n",
|
366 |
-
" ^^^^^^^^^^^^^^^^^^^^^^^^\n",
|
367 |
-
" File \"/Users/nadaa/.local/share/virtualenvs/srf_chatbot_v2-9vTIDuJW/lib/python3.11/site-packages/gradio/utils.py\", line 826, in wrapper\n",
|
368 |
-
" response = f(*args, **kwargs)\n",
|
369 |
-
" ^^^^^^^^^^^^^^^^^^\n",
|
370 |
-
" File \"/var/folders/wm/nll4dzqx2_n5zxq0y2h84cs40000gn/T/ipykernel_49088/3264473872.py\", line 24, in chatbot_conversation\n",
|
371 |
-
" result = respond(user_query, history)\n",
|
372 |
-
" ^^^^^^^\n",
|
373 |
-
"NameError: name 'history' is not defined\n"
|
374 |
-
]
|
375 |
}
|
376 |
],
|
377 |
"source": [
|
378 |
"import gradio as gr\n",
|
|
|
|
|
|
|
379 |
"\n",
|
380 |
-
"#
|
381 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
382 |
"\n",
|
383 |
-
"
|
384 |
-
"chatbot = SRFChatbot(chatbot_instructions=prompt_templates['Open-Ended Bot'])\n",
|
385 |
"\n",
|
386 |
-
"
|
387 |
-
" selected_prompt = prompt_templates[prompt_name]\n",
|
388 |
-
" chatbot = SRFChatbot(chatbot_instructions=selected_prompt)\n",
|
389 |
-
" return selected_prompt, [] # Return the prompt text and reset the chat history\n",
|
390 |
"\n",
|
391 |
-
"
|
392 |
-
"
|
393 |
-
" if chatbot is None:\n",
|
394 |
-
" # Initialize with default prompt if not already initialized\n",
|
395 |
-
" default_prompt = list(prompt_templates.keys())[0]\n",
|
396 |
-
" chatbot = SRFChatbot(chatbot_instructions=prompt_templates[default_prompt])\n",
|
397 |
-
" \n",
|
398 |
-
" \n",
|
399 |
-
" # Process the conversation\n",
|
400 |
-
" result = respond(user_query, history)\n",
|
401 |
-
" \n",
|
402 |
-
" # Extract the bot's response\n",
|
403 |
-
" bot_response = result[\"messages\"][-1].content\n",
|
404 |
-
" \n",
|
405 |
-
" # Update the chat history\n",
|
406 |
-
" chat_history.append((user_query, bot_response))\n",
|
407 |
-
" \n",
|
408 |
-
" return chat_history, \"\"\n",
|
409 |
"\n",
|
410 |
-
"# Gradio interface\n",
|
411 |
-
"with gr.Blocks(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
412 |
" gr.Markdown(\"# SRF Chatbot\")\n",
|
413 |
" \n",
|
414 |
-
" with gr.Row():\n",
|
415 |
-
" with gr.Column(scale=4):\n",
|
416 |
-
"
|
417 |
-
"
|
|
|
418 |
" submit_button = gr.Button(\"Submit\")\n",
|
419 |
" \n",
|
420 |
-
" with gr.Column(scale=1):\n",
|
|
|
421 |
" system_prompt_dropdown = gr.Dropdown(\n",
|
422 |
-
" choices=list(
|
423 |
-
" label=\"Select
|
424 |
-
" value=list(
|
|
|
425 |
" )\n",
|
|
|
426 |
" system_prompt_display = gr.Textbox(\n",
|
427 |
-
" value=
|
428 |
-
" label=\"Current
|
429 |
" lines=5,\n",
|
430 |
" interactive=False\n",
|
431 |
" )\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
432 |
" \n",
|
|
|
433 |
" system_prompt_dropdown.change(\n",
|
434 |
-
" fn=
|
435 |
" inputs=[system_prompt_dropdown],\n",
|
436 |
" outputs=[system_prompt_display]\n",
|
437 |
" )\n",
|
438 |
" \n",
|
|
|
439 |
" submit_button.click(\n",
|
440 |
-
" fn=
|
441 |
-
" inputs=[
|
442 |
-
" outputs=[chatbot_output]\n",
|
443 |
" )\n",
|
444 |
"\n",
|
445 |
-
"#
|
446 |
-
"
|
447 |
-
"\n",
|
448 |
-
"demo.launch()"
|
449 |
]
|
450 |
},
|
451 |
{
|
|
|
2 |
"cells": [
|
3 |
{
|
4 |
"cell_type": "code",
|
5 |
+
"execution_count": 30,
|
6 |
"metadata": {},
|
7 |
"outputs": [
|
8 |
{
|
|
|
51 |
},
|
52 |
{
|
53 |
"cell_type": "code",
|
54 |
+
"execution_count": 31,
|
55 |
"metadata": {},
|
56 |
"outputs": [],
|
57 |
"source": [
|
|
|
93 |
},
|
94 |
{
|
95 |
"cell_type": "code",
|
96 |
+
"execution_count": 32,
|
97 |
"metadata": {},
|
98 |
"outputs": [],
|
99 |
"source": [
|
|
|
|
|
|
|
|
|
|
|
100 |
"\n",
|
101 |
"class SRFChatbot:\n",
|
102 |
" def __init__(\n",
|
103 |
" self,\n",
|
104 |
+
" chatbot_instructions: str = sp.system_prompt_templates['Open-Ended Bot'],\n",
|
105 |
" model: str = 'gpt-4o-mini',\n",
|
106 |
" temperature: float = 0,\n",
|
107 |
" ):\n",
|
|
|
116 |
" # Get the configurable\n",
|
117 |
" self.config = self.get_configurable()\n",
|
118 |
" \n",
|
119 |
+
" def reset_system_prompt(self, chatbot_instructions_dropdown: str):\n",
|
120 |
+
" # Get chatbot instructions\n",
|
121 |
+
" chatbot_instructions = sp.system_prompt_templates[chatbot_instructions_dropdown]\n",
|
122 |
+
" # Reset the system prompt\n",
|
123 |
+
" self.system_message = SystemMessage(content=chatbot_instructions)\n",
|
124 |
+
" # Reset the configurable\n",
|
125 |
+
" self.config = self.get_configurable()\n",
|
126 |
+
"\n",
|
127 |
+
" return chatbot_instructions\n",
|
128 |
"\n",
|
129 |
" def get_configurable(self):\n",
|
130 |
+
" # This thread id is used to keep track of the chatbot's conversation\n",
|
131 |
" self.thread_id = str(uuid.uuid4())\n",
|
132 |
" return {\"configurable\": {\"thread_id\": self.thread_id}}\n",
|
133 |
" \n",
|
|
|
169 |
},
|
170 |
{
|
171 |
"cell_type": "code",
|
172 |
+
"execution_count": 33,
|
173 |
"metadata": {},
|
174 |
"outputs": [],
|
175 |
"source": [
|
176 |
+
"chatbot = SRFChatbot()\n"
|
|
|
177 |
]
|
178 |
},
|
179 |
{
|
180 |
"cell_type": "code",
|
181 |
+
"execution_count": 15,
|
182 |
"metadata": {},
|
183 |
"outputs": [],
|
184 |
"source": [
|
185 |
+
"query = \"Tell me more about reducing nervousness to improve sleep\"\n",
|
186 |
"results = chatbot.graph.invoke({\"messages\": [HumanMessage(content=query)]}, chatbot.config)"
|
187 |
]
|
188 |
},
|
189 |
{
|
190 |
"cell_type": "code",
|
191 |
+
"execution_count": 16,
|
192 |
+
"metadata": {},
|
193 |
+
"outputs": [
|
194 |
+
{
|
195 |
+
"name": "stdout",
|
196 |
+
"output_type": "stream",
|
197 |
+
"text": [
|
198 |
+
"To reduce nervousness and improve sleep, it is essential to recognize that much of our nervousness stems from our own reactions and emotional states. Paramhansa Yogananda emphasizes that restlessness and emotional excitement can overload the nervous system, leading to fatigue and anxiety. Engaging in deep meditation can help calm the nerves, as it allows the body to rest and rejuvenate. Additionally, dietary choices play a significant role; consuming calming foods such as whole grains, fruits, and avoiding stimulants like caffeine and alcohol can support a healthier nervous system. Practicing silence and reducing exposure to noise can also alleviate nervousness, creating a more peaceful environment conducive to sleep.\n",
|
199 |
+
"\n",
|
200 |
+
"**Quotes:**\n",
|
201 |
+
"1. \"You always blame other things for making you nervous, but never accuse yourself. Yet it is you who make yourself nervous; ninety-nine percent is your own fault.\" - *Journey to Self-Realization, Probing the Core of Nervousness*\n",
|
202 |
+
"2. \"When you stop overloading the nervous system, as when you are in deep sleep or a state of calmness in meditation, you are not nervous at all.\" - *Journey to Self-Realization, Probing the Core of Nervousness*\n",
|
203 |
+
"3. \"Learn to enjoy silence; don’t listen to the radio or television for hours on end, or have them blaring mindlessly in the background all the time.\" - *Journey to Self-Realization, Examine Yourself to See What Makes You Nervous*\n",
|
204 |
+
"4. \"The greatest healing of nervousness takes place when we attune our lives to God.\" - *Journey to Self-Realization, Attunement With God: Greatest Cure for Nervousness*\n",
|
205 |
+
"\n",
|
206 |
+
"**Recommended Reading:**\n",
|
207 |
+
"- *Journey to Self-Realization* by Paramhansa Yogananda\n",
|
208 |
+
"\n",
|
209 |
+
"**Follow-up Questions:**\n",
|
210 |
+
"1. What specific techniques can I use in meditation to calm my nerves?\n",
|
211 |
+
"2. Are there particular foods or drinks that are especially beneficial for reducing nervousness?\n",
|
212 |
+
"3. How can I create a more peaceful environment at home to improve my sleep?\n"
|
213 |
+
]
|
214 |
+
}
|
215 |
+
],
|
216 |
+
"source": [
|
217 |
+
"print(results['messages'][-1].content)"
|
218 |
+
]
|
219 |
+
},
|
220 |
+
{
|
221 |
+
"cell_type": "code",
|
222 |
+
"execution_count": 17,
|
223 |
"metadata": {},
|
224 |
"outputs": [
|
225 |
{
|
226 |
"data": {
|
227 |
"text/plain": [
|
228 |
+
"[HumanMessage(content='Tell me more about reducing nervousness to improve sleep', additional_kwargs={}, response_metadata={}, id='c1d3f9ba-0e06-4a6a-b38c-3dcd3be78bbf'),\n",
|
229 |
+
" AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_fjyQpF0pjUQZ8gobl2SAozXV', 'function': {'arguments': '{\"query\":\"reducing nervousness improve sleep\"}', 'name': 'vector_search'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 19, 'prompt_tokens': 433, 'total_tokens': 452, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_1bb46167f9', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-4a39fe1a-6413-4ba3-8aa3-290dc31a27bb-0', tool_calls=[{'name': 'vector_search', 'args': {'query': 'reducing nervousness improve sleep'}, 'id': 'call_fjyQpF0pjUQZ8gobl2SAozXV', 'type': 'tool_call'}], usage_metadata={'input_tokens': 433, 'output_tokens': 19, 'total_tokens': 452}),\n",
|
230 |
+
" ToolMessage(content=\"[Document(metadata={'chapter_name': 'Probing the Core of Nervousness', 'split_id_sequential': 418, 'split_id_uuid': '5ca2777d-c2a0-4e32-96b7-e43ed71c3aa2', 'publication_name': 'Journey to Self-Realization', '_id': '2151431e-7e07-44b6-8f33-7c8e277993c8', '_collection_name': 'openai_large_chunks_1500char'}, page_content='Probing the Core of Nervousness Self-Realization Fellowship Temple, San Diego, California, June 15, 1947 Everyone has at times been nervous, more or less, without knowing why. I may shake this piece of cloth and say it is nervous, but what is making the cloth move? When I cease moving my hand, the cloth lies limp. You always blame other things for making you nervous, but never accuse yourself. Yet it is you who make yourself nervous; ninety-nine percent is your own fault. Restlessness, emotional excitement, concentrates too much energy in the nerves so that they begin to wear out. After years and years, the adverse effects of that nervousness begin to show. The nerves are very tough—God made them so, because they have to last a lifetime—but it is necessary to give them proper care. When you stop overloading the nervous system, as when you are in deep sleep or a state of calmness in meditation, you are not nervous at all. In meditative ecstasy the nerves become highly rested and rejuvenated.'), Document(metadata={'split_id_sequential': 526, 'publication_name': 'Journey to Self-Realization', 'split_id_uuid': '2cecd1d8-68bf-4831-a6d2-de6028ff5fc5', 'chapter_name': 'The Best Diet for the Nerves', '_id': 'ff7b43a1-b42d-4983-8472-6eaeed695f4b', '_collection_name': 'openai_large_chunks_1500char'}, page_content='A yogic drink that is very good for the nervous system is made by adding crushed rock candy and fresh lime juice to a glass of water. It should be thoroughly mixed and evenly blended so that the taste is equally sweet and sour. I have recommended this to many people with excellent results. Another beneficial practice when you are very nervous is to take a cold bath. I once told this to a newspaperman. He said, “Well, if I did that every time I was nervous, I would have to carry a bathtub with me all the time!” I said, “Not necessary. Take a large piece of ice and rub it all over the body, especially over all the openings of the body. With this yoga technique, you will find that your nerves will become much calmer.”'), Document(metadata={'split_id_sequential': 525, 'publication_name': 'Journey to Self-Realization', 'chapter_name': 'The Best Diet for the Nerves', 'split_id_uuid': '5b366387-d311-486a-bc74-0559cb45d041', '_id': 'e2a33e74-64d8-47f4-9edd-41eebe277585', '_collection_name': 'openai_large_chunks_1500char'}, page_content='The Best Diet for the Nerves Even foods, which also are material condensations of astral rays of life, have effects that are correlated to their colour. Various kinds of natural white foods are good for the nervous system; they benefit the white matter of the brain. Berries are good for the gray matter of the brain—that is, blueberries or blackberries (which are really purple). Most fruits are gold in colour (or variants of gold, such as red and orange). As gold is the colour of the creative vibratory energy in matter, such fruits help the muscles, the blood, and the tissues. Goat’s milk, unbleached almonds, and raisins are very good for the nervous system. But all forms of meat of higher animals, especially beef and pork, are harmful to the nervous system; they are hyperstimulating and cause aggressiveness. Avoid too much starch, especially foods made from refined flour. Eat whole grains, cottage cheese, and plenty of fruits, fruit juices, and fresh vegetables—these are important. Needless to say, alcoholic beverages and drugs destroy the nervous system; stay away from them. A yogic drink that is very good for the nervous system is made by adding crushed rock candy and fresh lime juice to a glass of water. It should be thoroughly mixed and evenly blended so that the taste is equally sweet and sour. I have recommended this to many people with excellent results. Another beneficial practice when you are very nervous is to take a cold bath. I once told this to a newspaperman.'), Document(metadata={'chapter_name': 'Examine Yourself to See What Makes You Nervous', 'publication_name': 'Journey to Self-Realization', 'split_id_sequential': 160, 'split_id_uuid': '0900b6ab-2a48-48db-a66b-2ca0e80f9c70', '_id': 'de7f20d2-d3ac-45b6-8588-1a0b568e2ec9', '_collection_name': 'openai_large_chunks_1500char'}, page_content='Other cars were speeding past us on the steep, winding grade. I thought they were hurrying to get to the mountaintop in time to see the sunrise. To my great amazement, when we arrived we were the only ones outside to enjoy the view. All the others were in the restaurant drinking coffee and eating doughnuts. Imagine! They rushed to the top and then rushed back, just for the thrill of being able to say when they got home that they had been there, and had coffee and doughnuts on Pikes Peak. That is what nervousness does. We should take time to enjoy things—the beauties of God’s creation, the many blessings of life—but avoid undue excitement, restlessness, and sudden emotions, which burn up the nervous system. Talking too much, including the habit of engaging in long conversations on the telephone, creates nervousness. Habitual twitching—such as drumming the fingers or moving the toes—burns energy in the nerves. Another cause of nervousness, though you may not be aware of it, is the noise of the radio or television going on for hours at a time. All sounds cause the nerves to react.1 A study conducted in the police department in Chicago showed that if human beings were not subjected to the bombardment of the sounds of modern living, which are especially harsh in cities, they could live years longer. Learn to enjoy silence; don’t listen to the radio or television for hours on end, or have them blaring mindlessly in the background all the time.'), Document(metadata={'chapter_name': 'Attunement With God: Greatest Cure for Nervousness', 'split_id_sequential': 33, 'split_id_uuid': '28716ee9-dae2-46e5-80e6-f53bffa190c1', 'publication_name': 'Journey to Self-Realization', '_id': 'b079c905-181b-42ef-8c5f-849c0ba81f9b', '_collection_name': 'openai_large_chunks_1500char'}, page_content='Attunement With God: Greatest Cure for Nervousness Remember that the greatest healing of nervousness takes place when we attune our lives to God. The highest commandments given to man are to love God with all your heart, and with all your soul, and with all your mind, and with all your strength; and secondly, to love your neighbour as yourself.13 If you follow these, everything will come in its own way, and in the right way. It is not enough just to be a strict moralist—stones and goats do not break moral laws; still, they do not know God. But when you love God deeply enough, even if you are the greatest of sinners, you will be transformed and redeemed. The great saint Mirabai14 said, “To find the Divine One, the only indispensable is love.” That truth touched me deeply. All the prophets observe these two foremost commandments. Loving God with all your heart means to love Him with the love that you feel for the person who is dearest to you—with the love of the mother or father for the child, or the lover for the beloved. Give that kind of unconditional love to God. Loving God with all your soul means you can truly love Him when through deep meditation you know yourself as a soul, a child of God, made in His image. Loving God with all your mind means that when you are praying, your whole attention is on Him, not distracted by restless thoughts. In meditation, think only of God; don’t let the mind wander to everything else but God.')]\", name='vector_search', id='34f93038-5940-4a3b-bfd2-7f595ee69775', tool_call_id='call_fjyQpF0pjUQZ8gobl2SAozXV'),\n",
|
231 |
+
" AIMessage(content='To reduce nervousness and improve sleep, it is essential to recognize that much of our nervousness stems from our own reactions and emotional states. Paramhansa Yogananda emphasizes that restlessness and emotional excitement can overload the nervous system, leading to fatigue and anxiety. Engaging in deep meditation can help calm the nerves, as it allows the body to rest and rejuvenate. Additionally, dietary choices play a significant role; consuming calming foods such as whole grains, fruits, and avoiding stimulants like caffeine and alcohol can support a healthier nervous system. Practicing silence and reducing exposure to noise can also alleviate nervousness, creating a more peaceful environment conducive to sleep.\\n\\n**Quotes:**\\n1. \"You always blame other things for making you nervous, but never accuse yourself. Yet it is you who make yourself nervous; ninety-nine percent is your own fault.\" - *Journey to Self-Realization, Probing the Core of Nervousness*\\n2. \"When you stop overloading the nervous system, as when you are in deep sleep or a state of calmness in meditation, you are not nervous at all.\" - *Journey to Self-Realization, Probing the Core of Nervousness*\\n3. \"Learn to enjoy silence; don’t listen to the radio or television for hours on end, or have them blaring mindlessly in the background all the time.\" - *Journey to Self-Realization, Examine Yourself to See What Makes You Nervous*\\n4. \"The greatest healing of nervousness takes place when we attune our lives to God.\" - *Journey to Self-Realization, Attunement With God: Greatest Cure for Nervousness*\\n\\n**Recommended Reading:**\\n- *Journey to Self-Realization* by Paramhansa Yogananda\\n\\n**Follow-up Questions:**\\n1. What specific techniques can I use in meditation to calm my nerves?\\n2. Are there particular foods or drinks that are especially beneficial for reducing nervousness?\\n3. How can I create a more peaceful environment at home to improve my sleep?', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 416, 'prompt_tokens': 2347, 'total_tokens': 2763, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_1bb46167f9', 'finish_reason': 'stop', 'logprobs': None}, id='run-0814edcd-020f-4ae0-bab2-b696f9948fec-0', usage_metadata={'input_tokens': 2347, 'output_tokens': 416, 'total_tokens': 2763})]"
|
232 |
]
|
233 |
},
|
234 |
+
"execution_count": 17,
|
235 |
"metadata": {},
|
236 |
"output_type": "execute_result"
|
237 |
}
|
238 |
],
|
239 |
"source": [
|
240 |
+
"\n",
|
241 |
+
"chatbot.graph.get_state(chatbot.config)[0]['messages']"
|
242 |
]
|
243 |
},
|
244 |
{
|
245 |
"cell_type": "code",
|
246 |
+
"execution_count": 20,
|
247 |
+
"metadata": {},
|
248 |
+
"outputs": [],
|
249 |
+
"source": []
|
250 |
+
},
|
251 |
+
{
|
252 |
+
"cell_type": "code",
|
253 |
+
"execution_count": 35,
|
254 |
"metadata": {},
|
255 |
"outputs": [
|
256 |
{
|
257 |
"name": "stdout",
|
258 |
"output_type": "stream",
|
259 |
"text": [
|
260 |
+
"Running on local URL: http://127.0.0.1:7875\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
261 |
"\n",
|
262 |
+
"To create a public link, set `share=True` in `launch()`.\n"
|
|
|
|
|
263 |
]
|
264 |
+
},
|
265 |
+
{
|
266 |
+
"data": {
|
267 |
+
"text/html": [
|
268 |
+
"<div><iframe src=\"http://127.0.0.1:7875/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
|
269 |
+
],
|
270 |
+
"text/plain": [
|
271 |
+
"<IPython.core.display.HTML object>"
|
272 |
+
]
|
273 |
+
},
|
274 |
+
"metadata": {},
|
275 |
+
"output_type": "display_data"
|
276 |
+
},
|
277 |
+
{
|
278 |
+
"data": {
|
279 |
+
"text/plain": []
|
280 |
+
},
|
281 |
+
"execution_count": 35,
|
282 |
+
"metadata": {},
|
283 |
+
"output_type": "execute_result"
|
284 |
}
|
285 |
],
|
286 |
"source": [
|
287 |
+
"\n",
|
288 |
+
"def respond(query, history):\n",
|
289 |
+
"\n",
|
290 |
+
" formatted_query = [HumanMessage(content=query)]\n",
|
291 |
+
" # Invoke the graph with properly formatted input\n",
|
292 |
+
" result = chatbot.graph.invoke({\"messages\": formatted_query}, chatbot.config)\n",
|
293 |
+
" \n",
|
294 |
+
" # Extract the assistant's response\n",
|
295 |
+
" response = result[\"messages\"][-1].content\n",
|
296 |
+
"\n",
|
297 |
+
" history.append((query, response))\n",
|
298 |
+
"\n",
|
299 |
+
" \n",
|
300 |
+
" return history\n",
|
301 |
+
"\n",
|
302 |
+
"chatbot = SRFChatbot()\n",
|
303 |
+
"\n",
|
304 |
+
"# Gradio interface with responsive layout\n",
|
305 |
+
"with gr.Blocks(css=\"\"\"\n",
|
306 |
+
" @media (max-width: 600px) {\n",
|
307 |
+
" .gr-row { flex-direction: column !important; }\n",
|
308 |
+
" .gr-column { width: 100% !important; }\n",
|
309 |
+
" }\n",
|
310 |
+
"\"\"\") as demo:\n",
|
311 |
+
" gr.Markdown(\"# SRF Chatbot\")\n",
|
312 |
+
" \n",
|
313 |
+
" with gr.Row(elem_classes=\"gr-row\"):\n",
|
314 |
+
" with gr.Column(scale=4, elem_classes=\"gr-column\"):\n",
|
315 |
+
" chatbot_output = gr.Chatbot()\n",
|
316 |
+
" user_input = gr.Textbox(placeholder=\"Type your question here...\")\n",
|
317 |
+
" submit_button = gr.Button(\"Submit\")\n",
|
318 |
+
" \n",
|
319 |
+
" with gr.Column(scale=1, elem_classes=\"gr-column\"):\n",
|
320 |
+
" system_prompt_dropdown = gr.Dropdown(\n",
|
321 |
+
" choices=list(sp.system_prompt_templates.keys()),\n",
|
322 |
+
" label=\"Select Chatbot Instructions\",\n",
|
323 |
+
" value=list(sp.system_prompt_templates.keys())[0]\n",
|
324 |
+
" )\n",
|
325 |
+
" system_prompt_display = gr.Textbox(\n",
|
326 |
+
" value=sp.system_prompt_templates[list(sp.system_prompt_templates.keys())[0]],\n",
|
327 |
+
" label=\"Current Chatbot Instructions\",\n",
|
328 |
+
" lines=5,\n",
|
329 |
+
" interactive=False\n",
|
330 |
+
" )\n",
|
331 |
+
" \n",
|
332 |
+
" # Update system prompt display when a new prompt is selected\n",
|
333 |
+
" system_prompt_dropdown.change(\n",
|
334 |
+
" fn=chatbot.reset_system_prompt,\n",
|
335 |
+
" inputs=[system_prompt_dropdown],\n",
|
336 |
+
" outputs=[system_prompt_display]\n",
|
337 |
+
" )\n",
|
338 |
+
" \n",
|
339 |
+
" # Submit button logic to handle chatbot conversation\n",
|
340 |
+
" submit_button.click(\n",
|
341 |
+
" fn=respond,\n",
|
342 |
+
" inputs=[user_input, chatbot_output],\n",
|
343 |
+
" outputs=[chatbot_output]\n",
|
344 |
+
" )\n",
|
345 |
+
"\n",
|
346 |
+
"\n",
|
347 |
+
"demo.launch()\n"
|
348 |
]
|
349 |
},
|
350 |
{
|
351 |
"cell_type": "code",
|
352 |
+
"execution_count": 43,
|
353 |
"metadata": {},
|
354 |
"outputs": [
|
355 |
{
|
356 |
"name": "stdout",
|
357 |
"output_type": "stream",
|
358 |
"text": [
|
359 |
+
"Running on local URL: http://127.0.0.1:7883\n",
|
|
|
360 |
"\n",
|
361 |
+
"To create a public link, set `share=True` in `launch()`.\n"
|
362 |
]
|
363 |
},
|
364 |
{
|
365 |
"data": {
|
366 |
"text/html": [
|
367 |
+
"<div><iframe src=\"http://127.0.0.1:7883/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
|
368 |
],
|
369 |
"text/plain": [
|
370 |
"<IPython.core.display.HTML object>"
|
|
|
377 |
"data": {
|
378 |
"text/plain": []
|
379 |
},
|
380 |
+
"execution_count": 43,
|
381 |
"metadata": {},
|
382 |
"output_type": "execute_result"
|
383 |
}
|
384 |
],
|
385 |
"source": [
|
386 |
+
"import gradio as gr\n",
|
387 |
+
"\n",
|
388 |
+
"# Define the respond function\n",
|
389 |
+
"def respond(query, history):\n",
|
390 |
+
" formatted_query = [HumanMessage(content=query)]\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
391 |
" # Invoke the graph with properly formatted input\n",
|
392 |
+
" result = chatbot.graph.invoke({\"messages\": formatted_query}, chatbot.config)\n",
|
393 |
" \n",
|
394 |
" # Extract the assistant's response\n",
|
395 |
" response = result[\"messages\"][-1].content\n",
|
396 |
+
"\n",
|
397 |
+
" history.append((query, response))\n",
|
398 |
+
"\n",
|
399 |
+
" return history, \"\"\n",
|
400 |
+
"\n",
|
401 |
+
"# Initialize chatbot\n",
|
402 |
+
"chatbot = SRFChatbot()\n",
|
403 |
+
"\n",
|
404 |
+
"# Gradio interface with black and grey color scheme\n",
|
405 |
+
"with gr.Blocks(css=\"\"\"\n",
|
406 |
+
" .gradio-container {\n",
|
407 |
+
" background-color: #F0F0F0; \n",
|
408 |
+
" font-family: 'Arial', sans-serif;\n",
|
409 |
+
" }\n",
|
410 |
+
" h1, h2, p {\n",
|
411 |
+
" color: black;\n",
|
412 |
+
" }\n",
|
413 |
+
" h1 {\n",
|
414 |
+
" font-size: 32px;\n",
|
415 |
+
" text-align: left;\n",
|
416 |
+
" }\n",
|
417 |
+
" h2 {\n",
|
418 |
+
" font-size: 24px;\n",
|
419 |
+
" }\n",
|
420 |
+
" p {\n",
|
421 |
+
" font-size: 18px;\n",
|
422 |
+
" margin-bottom: 15px;\n",
|
423 |
+
" }\n",
|
424 |
+
" .gr-button {\n",
|
425 |
+
" background-color: #333333; \n",
|
426 |
+
" color: white;\n",
|
427 |
+
" font-size: 18px;\n",
|
428 |
+
" padding: 10px;\n",
|
429 |
+
" }\n",
|
430 |
+
" .gr-textbox textarea {\n",
|
431 |
+
" font-size: 18px;\n",
|
432 |
+
" color: black;\n",
|
433 |
+
" }\n",
|
434 |
+
" .gr-dropdown {\n",
|
435 |
+
" font-size: 18px;\n",
|
436 |
+
" color: black;\n",
|
437 |
+
" }\n",
|
438 |
+
" .source-box {\n",
|
439 |
+
" background-color: #D0D0D0; \n",
|
440 |
+
" padding: 10px; \n",
|
441 |
+
" border-radius: 8px; \n",
|
442 |
+
" margin-top: 20px;\n",
|
443 |
+
" color: black;\n",
|
444 |
+
" }\n",
|
445 |
+
" @media (max-width: 600px) {\n",
|
446 |
+
" .gr-row { flex-direction: column !important; }\n",
|
447 |
+
" .gr-column { width: 100% !important; }\n",
|
448 |
+
" }\n",
|
449 |
+
"\"\"\") as demo:\n",
|
450 |
+
" \n",
|
451 |
+
" # Title\n",
|
452 |
+
" gr.Markdown(\"# SRF Chatbot\")\n",
|
453 |
+
" \n",
|
454 |
+
" with gr.Row(elem_classes=\"gr-row\"):\n",
|
455 |
+
" with gr.Column(scale=4, elem_classes=\"gr-column\"):\n",
|
456 |
+
" # Chatbot interface\n",
|
457 |
+
" chatbot_output = gr.Chatbot()\n",
|
458 |
+
" user_input = gr.Textbox(placeholder=\"Type your question here...\", label=\"Your Question\")\n",
|
459 |
+
" submit_button = gr.Button(\"Submit\")\n",
|
460 |
+
" \n",
|
461 |
+
" with gr.Column(scale=1, elem_classes=\"gr-column\"):\n",
|
462 |
+
" # Dropdown to select system prompts\n",
|
463 |
+
" system_prompt_dropdown = gr.Dropdown(\n",
|
464 |
+
" choices=list(sp.system_prompt_templates.keys()),\n",
|
465 |
+
" label=\"Select Chatbot Instructions\",\n",
|
466 |
+
" value=list(sp.system_prompt_templates.keys())[0],\n",
|
467 |
+
" elem_classes=\"gr-dropdown\"\n",
|
468 |
+
" )\n",
|
469 |
+
" # Display the selected system prompt\n",
|
470 |
+
" system_prompt_display = gr.Textbox(\n",
|
471 |
+
" value=sp.system_prompt_templates[list(sp.system_prompt_templates.keys())[0]],\n",
|
472 |
+
" label=\"Current Chatbot Instructions\",\n",
|
473 |
+
" lines=5,\n",
|
474 |
+
" interactive=False\n",
|
475 |
+
" )\n",
|
476 |
+
" \n",
|
477 |
+
" # Sources box\n",
|
478 |
+
" gr.Markdown(\"\"\"\n",
|
479 |
+
" <div class=\"source-box\">\n",
|
480 |
+
" <strong>Available sources:</strong>\n",
|
481 |
+
" <ul>\n",
|
482 |
+
" <li>Journey to Self-Realization</li>\n",
|
483 |
+
" <li>The Second Coming of Christ</li>\n",
|
484 |
+
" <li>Autobiography of a Yogi</li>\n",
|
485 |
+
" </ul>\n",
|
486 |
+
" </div>\n",
|
487 |
+
" \"\"\")\n",
|
488 |
" \n",
|
489 |
+
" # Update system prompt display when a new prompt is selected\n",
|
490 |
+
" system_prompt_dropdown.change(\n",
|
491 |
+
" fn=chatbot.reset_system_prompt,\n",
|
492 |
+
" inputs=[system_prompt_dropdown],\n",
|
493 |
+
" outputs=[system_prompt_display]\n",
|
494 |
+
" )\n",
|
495 |
+
" \n",
|
496 |
+
" # Submit button logic to handle chatbot conversation\n",
|
497 |
+
" submit_button.click(\n",
|
498 |
+
" fn=respond,\n",
|
499 |
+
" inputs=[user_input, chatbot_output],\n",
|
500 |
+
" outputs=[chatbot_output, user_input]\n",
|
501 |
+
" )\n",
|
502 |
"\n",
|
503 |
+
"# Launch the interface\n",
|
504 |
+
"demo.launch()\n"
|
|
|
505 |
]
|
506 |
},
|
507 |
{
|
508 |
"cell_type": "code",
|
509 |
+
"execution_count": 44,
|
510 |
"metadata": {},
|
511 |
"outputs": [
|
512 |
{
|
513 |
"name": "stdout",
|
514 |
"output_type": "stream",
|
515 |
"text": [
|
516 |
+
"Running on local URL: http://127.0.0.1:7885\n",
|
517 |
"\n",
|
518 |
"To create a public link, set `share=True` in `launch()`.\n"
|
519 |
]
|
|
|
521 |
{
|
522 |
"data": {
|
523 |
"text/html": [
|
524 |
+
"<div><iframe src=\"http://127.0.0.1:7885/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
|
525 |
],
|
526 |
"text/plain": [
|
527 |
"<IPython.core.display.HTML object>"
|
|
|
534 |
"data": {
|
535 |
"text/plain": []
|
536 |
},
|
537 |
+
"execution_count": 44,
|
538 |
"metadata": {},
|
539 |
"output_type": "execute_result"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
540 |
}
|
541 |
],
|
542 |
"source": [
|
543 |
"import gradio as gr\n",
|
544 |
+
"import src.srf_bot as sb\n",
|
545 |
+
"import prompts.system_prompts as sp\n",
|
546 |
+
"from langchain_core.messages import HumanMessage \n",
|
547 |
"\n",
|
548 |
+
"# Define the respond function\n",
|
549 |
+
"def respond(query, history):\n",
|
550 |
+
" formatted_query = [HumanMessage(content=query)]\n",
|
551 |
+
" # Invoke the graph with properly formatted input\n",
|
552 |
+
" result = chatbot.graph.invoke({\"messages\": formatted_query}, chatbot.config)\n",
|
553 |
+
" \n",
|
554 |
+
" # Extract the assistant's response\n",
|
555 |
+
" response = result[\"messages\"][-1].content\n",
|
556 |
"\n",
|
557 |
+
" history.append((query, response))\n",
|
|
|
558 |
"\n",
|
559 |
+
" return history, \"\"\n",
|
|
|
|
|
|
|
560 |
"\n",
|
561 |
+
"# Initialize chatbot\n",
|
562 |
+
"chatbot = sb.SRFChatbot()\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
563 |
"\n",
|
564 |
+
"# Gradio interface with black and grey color scheme\n",
|
565 |
+
"with gr.Blocks(css=\"\"\"\n",
|
566 |
+
" .gradio-container {\n",
|
567 |
+
" background-color: #F0F0F0; \n",
|
568 |
+
" font-family: 'Arial', sans-serif;\n",
|
569 |
+
" }\n",
|
570 |
+
" h1, h2, p {\n",
|
571 |
+
" color: black;\n",
|
572 |
+
" }\n",
|
573 |
+
" h1 {\n",
|
574 |
+
" font-size: 32px;\n",
|
575 |
+
" text-align: left;\n",
|
576 |
+
" }\n",
|
577 |
+
" h2 {\n",
|
578 |
+
" font-size: 24px;\n",
|
579 |
+
" }\n",
|
580 |
+
" p {\n",
|
581 |
+
" font-size: 18px;\n",
|
582 |
+
" margin-bottom: 15px;\n",
|
583 |
+
" }\n",
|
584 |
+
" .gr-button {\n",
|
585 |
+
" background-color: #333333; \n",
|
586 |
+
" color: white;\n",
|
587 |
+
" font-size: 18px;\n",
|
588 |
+
" padding: 10px;\n",
|
589 |
+
" }\n",
|
590 |
+
" .gr-textbox textarea {\n",
|
591 |
+
" font-size: 18px;\n",
|
592 |
+
" color: black;\n",
|
593 |
+
" }\n",
|
594 |
+
" .gr-dropdown {\n",
|
595 |
+
" font-size: 18px;\n",
|
596 |
+
" color: black;\n",
|
597 |
+
" }\n",
|
598 |
+
" .source-box {\n",
|
599 |
+
" background-color: white; \n",
|
600 |
+
" padding: 10px; \n",
|
601 |
+
" border-radius: 8px; \n",
|
602 |
+
" margin-top: 20px;\n",
|
603 |
+
" color: black;\n",
|
604 |
+
" border: 1px solid #D0D0D0;\n",
|
605 |
+
" }\n",
|
606 |
+
" @media (max-width: 600px) {\n",
|
607 |
+
" .gr-row { flex-direction: column !important; }\n",
|
608 |
+
" .gr-column { width: 100% !important; }\n",
|
609 |
+
" }\n",
|
610 |
+
"\"\"\") as demo:\n",
|
611 |
+
" \n",
|
612 |
+
" # Title\n",
|
613 |
" gr.Markdown(\"# SRF Chatbot\")\n",
|
614 |
" \n",
|
615 |
+
" with gr.Row(elem_classes=\"gr-row\"):\n",
|
616 |
+
" with gr.Column(scale=4, elem_classes=\"gr-column\"):\n",
|
617 |
+
" # Chatbot interface\n",
|
618 |
+
" chatbot_output = gr.Chatbot(height=600) # Increased height for longer chat interface\n",
|
619 |
+
" user_input = gr.Textbox(placeholder=\"Type your question here...\", label=\"Your Question\")\n",
|
620 |
" submit_button = gr.Button(\"Submit\")\n",
|
621 |
" \n",
|
622 |
+
" with gr.Column(scale=1, elem_classes=\"gr-column\"):\n",
|
623 |
+
" # Dropdown to select system prompts\n",
|
624 |
" system_prompt_dropdown = gr.Dropdown(\n",
|
625 |
+
" choices=list(sp.system_prompt_templates.keys()),\n",
|
626 |
+
" label=\"Select Chatbot Instructions\",\n",
|
627 |
+
" value=list(sp.system_prompt_templates.keys())[0],\n",
|
628 |
+
" elem_classes=\"gr-dropdown\"\n",
|
629 |
" )\n",
|
630 |
+
" # Display the selected system prompt\n",
|
631 |
" system_prompt_display = gr.Textbox(\n",
|
632 |
+
" value=sp.system_prompt_templates[list(sp.system_prompt_templates.keys())[0]],\n",
|
633 |
+
" label=\"Current Chatbot Instructions\",\n",
|
634 |
" lines=5,\n",
|
635 |
" interactive=False\n",
|
636 |
" )\n",
|
637 |
+
" \n",
|
638 |
+
" # Sources box (Now white, matching the other boxes)\n",
|
639 |
+
" gr.Markdown(\"\"\"\n",
|
640 |
+
" <div class=\"source-box\">\n",
|
641 |
+
" <strong>Available sources:</strong>\n",
|
642 |
+
" <ul>\n",
|
643 |
+
" <li>Journey to Self-Realization</li>\n",
|
644 |
+
" <li>The Second Coming of Christ</li>\n",
|
645 |
+
" <li>Autobiography of a Yogi</li>\n",
|
646 |
+
" </ul>\n",
|
647 |
+
" </div>\n",
|
648 |
+
" \"\"\")\n",
|
649 |
" \n",
|
650 |
+
" # Update system prompt display when a new prompt is selected\n",
|
651 |
" system_prompt_dropdown.change(\n",
|
652 |
+
" fn=chatbot.reset_system_prompt,\n",
|
653 |
" inputs=[system_prompt_dropdown],\n",
|
654 |
" outputs=[system_prompt_display]\n",
|
655 |
" )\n",
|
656 |
" \n",
|
657 |
+
" # Submit button logic to handle chatbot conversation\n",
|
658 |
" submit_button.click(\n",
|
659 |
+
" fn=respond,\n",
|
660 |
+
" inputs=[user_input, chatbot_output],\n",
|
661 |
+
" outputs=[chatbot_output, user_input]\n",
|
662 |
" )\n",
|
663 |
"\n",
|
664 |
+
"# Launch the interface\n",
|
665 |
+
"demo.launch()\n"
|
|
|
|
|
666 |
]
|
667 |
},
|
668 |
{
|
notebooks/04 Return Passages.ipynb
ADDED
File without changes
|
notebooks/05 Scratch.ipynb
ADDED
File without changes
|
prompts/system_prompts.py
CHANGED
@@ -3,58 +3,48 @@
|
|
3 |
|
4 |
# System prompt options for the chatbot
|
5 |
system_prompt_templates = {
|
6 |
-
"Open-Ended Bot": '''You are a helpful assistant for people that want to query the teachings of Paramhansa Yogananda
|
7 |
-
and the Self-Realization Fellowship. Look up the vector database provided for relevant
|
8 |
-
passages to answer queries. Only use the context provided. Do not use any other sources.''',
|
9 |
|
10 |
-
"Question-Answer Bot with Quotes": """You are a helpful assistant
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
- Provide a list of quotes verbatim from the retrieved passages with source and chapter name
|
22 |
-
- Provide a list of recommended reading based on the retrieved passages
|
23 |
-
- Provide up to three suggestions for followup questions
|
24 |
-
- If the provided context does not contain the answer, please say so and ask the user to clarify their question.
|
25 |
-
""",
|
26 |
|
27 |
-
"Quote Finder": '''You are a helpful assistant
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
- Provide up to three suggestions for followup quote searches
|
39 |
-
- Do not paraphrase the quotes into an answer. Return the quotes directly.''',
|
40 |
|
41 |
"Passage Finder": '''You are a helpful assistant that finds passages from the teachings of Paramhansa Yogananda and
|
42 |
-
|
43 |
-
|
|
|
44 |
|
45 |
"Subtopic Finder and Deep Dive": '''You are a helpful assistant that generates subtopics for a given topic or question from the teachings of Paramhansa Yogananda and the Self-Realization Fellowship
|
46 |
-
|
47 |
-
|
48 |
-
For each sub-topic, provide a concise summary of the sub-topic and a list of recommended readings
|
49 |
-
from the teachings of Paramhansa Yogananda and the Self-Realization Fellowship.''',
|
50 |
|
51 |
"In Depth Topic Summary": '''You are a helpful assistant that summarizes topics from the teachings of Paramhansa Yogananda and the Self-Realization Fellowship.
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
|
59 |
}
|
60 |
|
|
|
3 |
|
4 |
# System prompt options for the chatbot
|
5 |
system_prompt_templates = {
|
6 |
+
"Open-Ended Bot": '''You are a helpful assistant for people that want to query the teachings of Paramhansa Yogananda and the Self-Realization Fellowship. Look up the vector database provided for relevantpassages to answer queries. Only use the context provided. Do not use any other sources.''',
|
|
|
|
|
7 |
|
8 |
+
"Question-Answer Bot with Quotes": """You are a helpful assistant that can query the teachings of Paramhansa Yogananda and the Self-Realization Fellowship from a vector database.
|
9 |
+
You will only answer questions based on the provided context.
|
10 |
+
Instructions:
|
11 |
+
- Ask follow-up questions if needed to clarify the question
|
12 |
+
- Query the vector database multiple times if the user query contains a question or questions that span multiple topics
|
13 |
+
Output Format
|
14 |
+
- The answer should be one paragraph and only be derived from the context provided
|
15 |
+
- Provide a list of quotes verbatim from the retrieved passages with source and chapter name
|
16 |
+
- Provide a list of recommended reading based on the retrieved passages
|
17 |
+
- Provide up to three suggestions for followup questions
|
18 |
+
- If the provided context does not contain the answer, please say so and ask the user to clarify their question.""",
|
|
|
|
|
|
|
|
|
|
|
19 |
|
20 |
+
"Quote Finder": '''You are a helpful assistant that can query a vector database for the teachings of
|
21 |
+
Paramhansa Yogananda and the Self-Realization Fellowship related to a give topic or question.
|
22 |
+
In some cases, the user may describe a life problem or scenario. In you should break up the user query into
|
23 |
+
multiple search queries. Only extract quotes from the passages in the provided context. Ensure that the quotes are verbatim.
|
24 |
+
Here are further instructions:
|
25 |
+
- Ask follow-up questions if needed to clarify the question or topic
|
26 |
+
- Query the vector database multiple times if the user query contains spans multiple topics
|
27 |
+
- Include the source and chapter name for each quote you provide.
|
28 |
+
- Provide a list of recommended reading
|
29 |
+
- Provide up to three suggestions for followup quote searches
|
30 |
+
- Do not paraphrase the quotes into an answer. Return the quotes directly.''',
|
|
|
|
|
31 |
|
32 |
"Passage Finder": '''You are a helpful assistant that finds passages from the teachings of Paramhansa Yogananda and
|
33 |
+
the Self-Realization Fellowship that are related to a given topic or question from a vector database. Output
|
34 |
+
the full passages provided in the context. Organize them by relevance to the user query. Bold quotes that
|
35 |
+
are particularly insightful or relevant to the user query.''',
|
36 |
|
37 |
"Subtopic Finder and Deep Dive": '''You are a helpful assistant that generates subtopics for a given topic or question from the teachings of Paramhansa Yogananda and the Self-Realization Fellowship
|
38 |
+
and allows users to do a deep dive into those subtopics. Retrieve at least 20 passages from the vector database for the given topic and then list out sub-topics that emerge from the retrieved passages.
|
39 |
+
For each sub-topic, provide a concise summary of the sub-topic and a list of recommended readings from the teachings of Paramhansa Yogananda and the Self-Realization Fellowship.''',
|
|
|
|
|
40 |
|
41 |
"In Depth Topic Summary": '''You are a helpful assistant that summarizes topics from the teachings of Paramhansa Yogananda and the Self-Realization Fellowship.
|
42 |
+
Provide a detailed summary of the topic and a list of recommended readings from the teachings of
|
43 |
+
Paramhansa Yogananda and the Self-Realization Fellowship. Your summaries should only use information from the provided context.
|
44 |
+
Do not include information outside of the context provided. The summaries should be comprehensive and provide a deep understanding of the topic.
|
45 |
+
The summaries should be in a paragraph format. At the end of the summary provide supporting quotes and resources.
|
46 |
+
Make multiple queries to the vector database to retrieve information to answer the user's question if needed.
|
47 |
+
Also ask follow-up questions to clarify the user's question if needed.''',
|
48 |
|
49 |
}
|
50 |
|
src/srf_bot.py
CHANGED
@@ -0,0 +1,172 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import sys
|
2 |
+
import os
|
3 |
+
import uuid
|
4 |
+
from dotenv import load_dotenv
|
5 |
+
from typing import Annotated, List, Tuple
|
6 |
+
from typing_extensions import TypedDict
|
7 |
+
from langchain.tools import tool, BaseTool
|
8 |
+
from langchain.schema import Document
|
9 |
+
from langgraph.graph import StateGraph, START, END, MessagesState
|
10 |
+
from langgraph.graph.message import add_messages
|
11 |
+
from langgraph.prebuilt import ToolNode, tools_condition
|
12 |
+
from langgraph.checkpoint.memory import MemorySaver
|
13 |
+
from langchain_openai import ChatOpenAI
|
14 |
+
from langchain_core.prompts import ChatPromptTemplate, SystemMessagePromptTemplate, AIMessagePromptTemplate, HumanMessagePromptTemplate
|
15 |
+
# from langchain.schema import SystemMessage, HumanMessage, AIMessage, ToolMessage
|
16 |
+
from langchain_core.messages import HumanMessage, AIMessage, ToolMessage, SystemMessage
|
17 |
+
from langchain.retrievers.multi_query import MultiQueryRetriever
|
18 |
+
import json
|
19 |
+
sys.path.append(os.path.abspath('..'))
|
20 |
+
|
21 |
+
|
22 |
+
import src.utils.qdrant_manager as qm
|
23 |
+
import prompts.system_prompts as sp
|
24 |
+
|
25 |
+
load_dotenv('/Users/nadaa/Documents/code/py_innovations/srf_chatbot_v2/.env')
|
26 |
+
|
27 |
+
|
28 |
+
class ToolManager:
|
29 |
+
def __init__(self, collection_name="openai_large_chunks_1500char"):
|
30 |
+
self.tools = []
|
31 |
+
self.qdrant = qm.QdrantManager(collection_name=collection_name)
|
32 |
+
self.vectorstore = self.qdrant.get_vectorstore()
|
33 |
+
self.add_tools()
|
34 |
+
|
35 |
+
def get_tools(self):
|
36 |
+
return self.tools
|
37 |
+
|
38 |
+
def add_tools(self):
|
39 |
+
@tool
|
40 |
+
def vector_search(query: str, k: int = 5) -> list[Document]:
|
41 |
+
"""Useful for simple queries. This tool will search a vector database for passages from the teachings of Paramhansa Yogananda and other publications from the Self Realization Fellowship (SRF).
|
42 |
+
The user has the option to specify the number of passages they want the search to return, otherwise the number of passages will be set to the default value."""
|
43 |
+
retriever = self.vectorstore.as_retriever(search_kwargs={"k": k})
|
44 |
+
documents = retriever.invoke(query)
|
45 |
+
return documents
|
46 |
+
|
47 |
+
@tool
|
48 |
+
def multiple_query_vector_search(query: str, k: int = 5) -> list[Document]:
|
49 |
+
"""Useful when the user's query is vague, complex, or involves multiple concepts.
|
50 |
+
This tool will write multiple versions of the user's query and search the vector database for relevant passages.
|
51 |
+
Use this tool when the user asks for an in depth answer to their question."""
|
52 |
+
|
53 |
+
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.5)
|
54 |
+
retriever_from_llm = MultiQueryRetriever.from_llm(retriever=self.vectorstore.as_retriever(), llm=llm)
|
55 |
+
documents = retriever_from_llm.invoke(query)
|
56 |
+
return documents
|
57 |
+
|
58 |
+
self.tools.append(vector_search)
|
59 |
+
self.tools.append(multiple_query_vector_search)
|
60 |
+
|
61 |
+
class BasicToolNode:
|
62 |
+
"""A node that runs the tools requested in the last AIMessage."""
|
63 |
+
|
64 |
+
def __init__(self, tools: list) -> None:
|
65 |
+
self.tools_by_name = {tool.name: tool for tool in tools}
|
66 |
+
|
67 |
+
def __call__(self, inputs: dict):
|
68 |
+
if messages := inputs.get("messages", []):
|
69 |
+
message = messages[-1]
|
70 |
+
else:
|
71 |
+
raise ValueError("No message found in input")
|
72 |
+
outputs = []
|
73 |
+
documents = []
|
74 |
+
for tool_call in message.tool_calls:
|
75 |
+
tool_result = self.tools_by_name[tool_call["name"]].invoke(
|
76 |
+
tool_call["args"]
|
77 |
+
)
|
78 |
+
outputs.append(
|
79 |
+
ToolMessage(
|
80 |
+
content=str(tool_result),
|
81 |
+
name=tool_call["name"],
|
82 |
+
tool_call_id=tool_call["id"],
|
83 |
+
)
|
84 |
+
)
|
85 |
+
documents += tool_result
|
86 |
+
|
87 |
+
return {"messages": outputs, "documents": documents}
|
88 |
+
|
89 |
+
class AgentState(TypedDict):
|
90 |
+
|
91 |
+
messages: Annotated[list, add_messages]
|
92 |
+
documents: list[Document]
|
93 |
+
system_message: list[SystemMessage]
|
94 |
+
system_message_dropdown: list[str]
|
95 |
+
|
96 |
+
class SRFChatbot:
|
97 |
+
def __init__(
|
98 |
+
self,
|
99 |
+
chatbot_instructions_dropdown: str = 'Open-Ended Bot',
|
100 |
+
model: str = 'gpt-4o-mini',
|
101 |
+
temperature: float = 0,
|
102 |
+
):
|
103 |
+
# Initialize the LLM and the system message
|
104 |
+
## THIS SHOULD BE REFACTORED AS THERE IS REPEITITION OF THE CODE IN RESET SYSTEM PROMPT TOO
|
105 |
+
self.chatbot_instructions_dropdown = chatbot_instructions_dropdown
|
106 |
+
self.chatbot_instructions = sp.system_prompt_templates[self.chatbot_instructions_dropdown]
|
107 |
+
self.system_message = SystemMessage(content=self.chatbot_instructions)
|
108 |
+
|
109 |
+
self.llm = ChatOpenAI(model=model, temperature=temperature)
|
110 |
+
self.tools = ToolManager().get_tools()
|
111 |
+
self.llm_with_tools = self.llm.bind_tools(self.tools)
|
112 |
+
|
113 |
+
# Build the graph
|
114 |
+
self.graph = self.build_graph()
|
115 |
+
# Get the configurable
|
116 |
+
self.config = self.get_configurable()
|
117 |
+
|
118 |
+
def reset_system_prompt(self, chatbot_instructions_dropdown: str):
|
119 |
+
# Update the dropdown
|
120 |
+
self.chatbot_instructions_dropdown = chatbot_instructions_dropdown
|
121 |
+
# Get chatbot instructions
|
122 |
+
self.chatbot_instructions = sp.system_prompt_templates[self.chatbot_instructions_dropdown]
|
123 |
+
# Reset the system prompt
|
124 |
+
self.system_message = SystemMessage(content=self.chatbot_instructions)
|
125 |
+
# Reset the configurable
|
126 |
+
self.config = self.get_configurable()
|
127 |
+
return self.chatbot_instructions
|
128 |
+
|
129 |
+
def get_configurable(self):
|
130 |
+
# This thread id is used to keep track of the chatbot's conversation
|
131 |
+
self.thread_id = str(uuid.uuid4())
|
132 |
+
return {"configurable": {"thread_id": self.thread_id}}
|
133 |
+
|
134 |
+
def get_system_message_dropdown(self):
|
135 |
+
return self.graph.get_state(config=self.config).values['system_message_dropdown']
|
136 |
+
|
137 |
+
# Add the system message onto the llm
|
138 |
+
## THIS SHOULD BE REFACTORED SO THAT THE STATE ALWAYS HAS THE DEFINITIVE SYSTEM MESSAGE THAT SHOULD BE IN USE
|
139 |
+
def chatbot(self, state: AgentState):
|
140 |
+
messages = [self.system_message] + state["messages"]
|
141 |
+
return {"messages": [self.llm_with_tools.invoke(messages)], "system_message": self.system_message, "system_message_dropdown": self.chatbot_instructions_dropdown}
|
142 |
+
|
143 |
+
def build_graph(self):
|
144 |
+
# Add chatbot state
|
145 |
+
graph_builder = StateGraph(AgentState)
|
146 |
+
|
147 |
+
# Add nodes
|
148 |
+
tool_node = BasicToolNode(tools=self.tools)
|
149 |
+
# tool_node = ToolNode(self.tools)
|
150 |
+
graph_builder.add_node("tools", tool_node)
|
151 |
+
graph_builder.add_node("chatbot", self.chatbot)
|
152 |
+
|
153 |
+
# Add a conditional edge wherein the chatbot can decide whether or not to go to the tools
|
154 |
+
graph_builder.add_conditional_edges(
|
155 |
+
"chatbot",
|
156 |
+
tools_condition,
|
157 |
+
)
|
158 |
+
|
159 |
+
# Add fixed edges
|
160 |
+
graph_builder.add_edge(START, "chatbot")
|
161 |
+
graph_builder.add_edge("tools", "chatbot")
|
162 |
+
|
163 |
+
# Instantiate the memory saver
|
164 |
+
memory = MemorySaver()
|
165 |
+
|
166 |
+
# Compile the graph
|
167 |
+
return graph_builder.compile(checkpointer=memory)
|
168 |
+
|
169 |
+
|
170 |
+
|
171 |
+
|
172 |
+
|