|
import streamlit as st |
|
from socratic import * |
|
from tool import get_tools |
|
from agent import Agent |
|
from common import get_llm |
|
import sys |
|
import time |
|
import random |
|
|
|
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) |
|
|
|
|
|
|
|
PAGE_TITLE: str = "Socratiq" |
|
PAGE_ICON: str = "🗨️" |
|
N_ROUND: int = 50 |
|
|
|
st.set_page_config(page_title=PAGE_TITLE, page_icon=PAGE_ICON) |
|
|
|
open_api_key = st.secrets["OPENAI_API_KEY"] |
|
st.session_state.key = open_api_key |
|
|
|
|
|
def init_session() -> None: |
|
tools = get_tools() |
|
st.session_state.agent = Agent(get_llm(model_name='gpt-4o', model_temperature=0, api_key=st.session_state.key), |
|
tools) |
|
st.session_state.socrates = SocraticGPT(role=SOCRATES, tools=st.session_state.agent._tools, |
|
key=st.session_state.key, n_round=N_ROUND) |
|
st.session_state.theaetetus = SocraticGPT(role=THEAETETUS, tools=st.session_state.agent._tools, |
|
key=st.session_state.key, n_round=N_ROUND) |
|
st.session_state.plato = SocraticGPT(role=PLATO, tools=st.session_state.agent._tools, key=st.session_state.key, |
|
n_round=N_ROUND) |
|
st.session_state.dialog_lead = None |
|
st.session_state.dialog_follower = None |
|
st.session_state.messages = [] |
|
st.session_state.question = None |
|
st.session_state.user_input = None |
|
st.session_state.in_progress = False |
|
st.session_state.user_question = None |
|
|
|
|
|
def get_random_question(): |
|
return "What is the size of the Moon?" if random.randint(1,10) % 3 == 0 else "What is love?" |
|
|
|
|
|
def show_intro_screen(): |
|
st.header("Socratiq") |
|
st.image("./assets/intro-trio.jpg") |
|
description = """\ |
|
You ask, 'What's the meaning of life?' and our trio of digital philosophers fetch real-time |
|
wisdom faster than you can say 'Immanuel Kant.' Whether you’re curious about science, or even the nuances of |
|
modern art, Soratiq has you covered. |
|
""" |
|
st.caption(description) |
|
|
|
if st.session_state.question is None: |
|
question = st.text_input(label='Paste your question. E.g. "What is the size of the moon?"', |
|
label_visibility='collapsed', |
|
placeholder='Paste your question. E.g. "What is the size of the moon?"') |
|
col1, _, _, _, col2 = st.columns(5) |
|
if col1.button(label="Ask Away!", help="Push the button and dive into the dialog around your question..."): |
|
if not len(question) > 0: |
|
st.warning( |
|
"Whoops! That question seems to be doing the vanishing act. Could you give it another shot? Magic words: 'Valid question, Please!' 🪄") |
|
if len(question) > 0: |
|
set_user_question(question) |
|
|
|
if col2.button(label="QuestionRoll", help="The button generates a random question for the user to ponder or discuss. This should be a fun and engaging experience, sparking curiosity."): |
|
question = get_random_question() |
|
set_user_question(question) |
|
|
|
st.divider() |
|
with st.expander("Who are they? What's going on?"): |
|
st.markdown("""\ |
|
Imagine you've just stepped into an intellectual arena that's as engaging as a top-tier debate club and as lively as your favorite coffeehouse. Like the brainstorming session you've always dreamed of. |
|
- First up, **you're the Maestro**. With a simple thumbs-up or down, you steer this conversation, helping to sculpt the dialogue into something meaningful. Your feedback is the compass. |
|
|
|
- Next, we have **Socrates and Theaetetus**, your co-pilots in this philosophical flight. They serve up questions designed to delve deep into the core of the matter. |
|
|
|
- **Plato's on board too**, adding a layer of logical critique to ensure our dialogue doesn't go off the rails. |
|
|
|
- Finally, meet the **Agent**, our whiz at rapid information retrieval. This isn't just Googling; think of it as real-time fact-checking with a dash of AI brilliance, you'd think it had a Ph.D. in Searchology. |
|
|
|
Try `QuestionRoll` and get a random question to watch how it goes. [More details](https://princeton-nlp.github.io/SocraticAI/) |
|
""") |
|
else: |
|
if st.session_state.question is not None: |
|
st.subheader(f"*{st.session_state.question}*") |
|
st.divider() |
|
|
|
|
|
|
|
def set_user_question(question): |
|
st.session_state.question = question |
|
st.session_state.socrates.set_question(question) |
|
st.session_state.theaetetus.set_question(question) |
|
st.session_state.plato.set_question(question) |
|
st.experimental_rerun() |
|
|
|
|
|
if 'question' not in st.session_state: |
|
init_session() |
|
|
|
def get_avatar(role): |
|
if role == SOCRATES: |
|
return "./assets/socrates-avatar.jpg" |
|
elif role == THEAETETUS: |
|
return "./assets/theatetus-avatar.png" |
|
elif role == PLATO: |
|
return "./assets/plato-avatar.jpg" |
|
elif role == 'agent': |
|
return "ai" |
|
elif role == 'system': |
|
return "./assets/agent-avatar.jpg" |
|
elif role == 'user': |
|
return "user" |
|
|
|
def get_role(role): |
|
if role == 'agent': |
|
return 'ai' |
|
elif role == 'system': |
|
return 'ai' |
|
else: |
|
return 'user' |
|
|
|
def show_chat() -> None: |
|
if st.session_state.messages: |
|
for message in st.session_state.messages: |
|
role = message['role'] |
|
content = message['content'] |
|
with st.chat_message(get_role(role), avatar=get_avatar(role)): |
|
if role == 'system': |
|
st.markdown("*" + content + "*") |
|
else: |
|
st.markdown(content) |
|
|
|
|
|
def add_message(role, content): |
|
st.session_state.messages.append({"role": role, "content": content}) |
|
with st.chat_message(get_role(role), avatar=get_avatar(role)): |
|
st.markdown(content) |
|
|
|
|
|
def chat_input(): |
|
if st.session_state.user_question is not None: |
|
prompt = st.chat_input("Share your wisdom...") |
|
if prompt: |
|
st.session_state.user_input = prompt |
|
elif st.session_state.question is not None: |
|
st.chat_input("...", disabled=True) |
|
|
|
def main() -> None: |
|
show_intro_screen() |
|
chat_input() |
|
show_chat() |
|
|
|
if st.session_state.question is not None and st.session_state.user_question is None: |
|
if not st.session_state.in_progress: |
|
st.session_state.in_progress = True |
|
st.session_state.dialog_lead, st.session_state.dialog_follower = st.session_state.socrates, st.session_state.theaetetus |
|
|
|
|
|
else: |
|
with st.spinner(f"{st.session_state.dialog_follower.role} is thinking..."): |
|
rep = st.session_state.dialog_follower.get_response() |
|
add_message(st.session_state.dialog_follower.role, f"{st.session_state.dialog_follower.role}: " + rep) |
|
st.session_state.dialog_lead.update_history(rep) |
|
st.session_state.plato.update_history(f"{st.session_state.dialog_follower.role}: " + rep) |
|
|
|
|
|
st.session_state.dialog_lead, st.session_state.dialog_follower = st.session_state.dialog_follower, st.session_state.dialog_lead |
|
|
|
answer = SocraticGPT.get_answer(rep) |
|
user_question = SocraticGPT.get_user_question(rep) |
|
agent_question = SocraticGPT.get_agent_question(rep) |
|
|
|
if st.session_state.dialog_lead.role == st.session_state.theaetetus.role: |
|
if user_question is None and agent_question is None and answer is None: |
|
with st.spinner(f"thinking critically..."): |
|
pr = st.session_state.plato.get_proofread() |
|
if pr: |
|
add_message(st.session_state.plato.role, f"{st.session_state.plato.role}: " + pr) |
|
st.session_state.socrates.add_proofread(pr) |
|
st.session_state.theaetetus.add_proofread(pr) |
|
user_question = SocraticGPT.get_user_question(pr) |
|
agent_question = SocraticGPT.get_agent_question(pr) |
|
|
|
if agent_question: |
|
with st.status(f"Consulting the agent: ''' {agent_question} '''"): |
|
agent_msg = st.session_state.agent.run(agent_question) |
|
st.session_state.socrates.add_agent_feedback(agent_question, agent_msg) |
|
st.session_state.theaetetus.add_agent_feedback(agent_question, agent_msg) |
|
st.session_state.plato.add_agent_feedback(agent_question, agent_msg) |
|
add_message('agent', f"Agent: {agent_msg}") |
|
|
|
if user_question: |
|
st.session_state.user_question = user_question |
|
add_message('system', f'User feedback is required. The question: **"{" ".join(user_question)}"**') |
|
st.experimental_rerun() |
|
|
|
if answer: |
|
st.session_state.user_question = f"Is that correct answer? - {answer}" |
|
add_message('system', f"""User, are you agree with the answer? - **{" ".join(answer)}**""") |
|
st.experimental_rerun() |
|
|
|
if st.session_state.user_input is not None: |
|
user_input = st.session_state.user_input |
|
if st.session_state.user_question is not None: |
|
user_question = st.session_state.user_question |
|
st.session_state.socrates.add_user_feedback(user_question, user_input) |
|
st.session_state.theaetetus.add_user_feedback(user_question, user_input) |
|
st.session_state.plato.add_user_feedback(user_question, user_input) |
|
st.session_state.user_question = None |
|
add_message("user", f"{user_input}") |
|
|
|
st.session_state.user_input = None |
|
|
|
if st.session_state.question is not None and st.session_state.user_question is None: |
|
time.sleep(1) |
|
st.experimental_rerun() |
|
|
|
|
|
if __name__ == "__main__": |
|
main() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|