modified: slop_with_models.py modified: streamlit_slop_with_models.py
507 lines
22 KiB
Python
507 lines
22 KiB
Python
import streamlit as st
|
||
import requests
|
||
import logging
|
||
|
||
# Configure logging to output to terminal for debugging
|
||
logging.basicConfig(
|
||
level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s"
|
||
)
|
||
logger = logging.getLogger(__name__)
|
||
|
||
# API endpoint
|
||
# BASE_URL = "http://localhost:31337"
|
||
BASE_URL = "https://slop.unturf.com"
|
||
|
||
|
||
def main():
|
||
st.title("SLOP Streamlit with Dynamic Models")
|
||
st.markdown(
|
||
"[Explore API Documentation](https://slop.unturf.com/openapi/)",
|
||
unsafe_allow_html=True,
|
||
)
|
||
page = st.sidebar.selectbox(
|
||
"Choose a feature", ["Chat", "Tools", "Memory", "Resources", "Pay"]
|
||
)
|
||
if page == "Chat":
|
||
chat_interface()
|
||
elif page == "Tools":
|
||
tools_interface()
|
||
elif page == "Memory":
|
||
memory_interface()
|
||
elif page == "Resources":
|
||
resources_interface()
|
||
elif page == "Pay":
|
||
pay_interface()
|
||
|
||
|
||
def chat_interface():
|
||
st.header("Chat")
|
||
|
||
try:
|
||
response = requests.get(f"{BASE_URL}/models", timeout=5)
|
||
response.raise_for_status()
|
||
models = response.json()["models"]
|
||
except requests.RequestException as e:
|
||
st.warning(f"Could not fetch models: {str(e)}")
|
||
models = []
|
||
|
||
selected_model = st.selectbox(
|
||
"Select Model", models if models else ["No models available"]
|
||
)
|
||
|
||
if "chat_history" not in st.session_state:
|
||
st.session_state.chat_history = []
|
||
|
||
for entry in st.session_state.chat_history:
|
||
st.write(f"**User**: {entry['user']}")
|
||
st.write(f"**Assistant**: {entry['assistant']}")
|
||
|
||
with st.form(key="chat_form", clear_on_submit=True):
|
||
message = st.text_area("Enter your message", height=100, key="chat_input")
|
||
submit_button = st.form_submit_button(label="Submit", type="primary")
|
||
|
||
st.markdown(
|
||
"""
|
||
<script>
|
||
const textarea = document.querySelector('textarea');
|
||
textarea.addEventListener('keydown', function(event) {
|
||
if (event.key === 'Enter' && !event.shiftKey) {
|
||
event.preventDefault();
|
||
document.querySelector('button[type="submit"]').click();
|
||
}
|
||
});
|
||
</script>
|
||
""",
|
||
unsafe_allow_html=True,
|
||
)
|
||
|
||
if submit_button and message and models:
|
||
try:
|
||
response = requests.post(
|
||
f"{BASE_URL}/chat",
|
||
json={
|
||
"messages": [{"role": "user", "content": message}],
|
||
"model": selected_model,
|
||
},
|
||
timeout=300,
|
||
)
|
||
response.raise_for_status()
|
||
assistant_response = response.json()["choices"][0]["message"]["content"]
|
||
st.session_state.chat_history.append(
|
||
{"user": message, "assistant": assistant_response}
|
||
)
|
||
st.rerun()
|
||
except requests.RequestException as e:
|
||
st.error(f"Error: {str(e)}")
|
||
|
||
|
||
def tools_interface():
|
||
st.header("Tools")
|
||
try:
|
||
response = requests.get(f"{BASE_URL}/tools", timeout=5)
|
||
response.raise_for_status()
|
||
tools = response.json()["tools"]
|
||
except requests.RequestException as e:
|
||
st.warning(f"Could not fetch tools: {str(e)}")
|
||
tools = []
|
||
|
||
if not tools:
|
||
st.write("No tools available.")
|
||
return
|
||
|
||
tool_id = st.selectbox("Select a tool", [t["id"] for t in tools])
|
||
|
||
if tool_id == "calculator":
|
||
expression = st.text_input("Enter expression (e.g., 2 + 2)")
|
||
if st.button("Calculate"):
|
||
try:
|
||
response = requests.post(
|
||
f"{BASE_URL}/tools/{tool_id}",
|
||
json={"expression": expression},
|
||
timeout=5,
|
||
)
|
||
response.raise_for_status()
|
||
st.write(f"Result: {response.json()['result']}")
|
||
except requests.RequestException as e:
|
||
st.error(f"Error: {str(e)}")
|
||
|
||
elif tool_id == "greet":
|
||
name = st.text_input("Enter name")
|
||
if st.button("Greet"):
|
||
try:
|
||
response = requests.post(
|
||
f"{BASE_URL}/tools/{tool_id}", json={"name": name}, timeout=5
|
||
)
|
||
response.raise_for_status()
|
||
st.write(response.json()["result"])
|
||
except requests.RequestException as e:
|
||
st.error(f"Error: {str(e)}")
|
||
|
||
elif tool_id == "slots":
|
||
st.subheader("Slots")
|
||
agent_id = st.text_input("Your Agent ID", value="player1")
|
||
bet = st.number_input("Bet Amount", min_value=1, step=1, value=10)
|
||
if st.button("Spin"):
|
||
try:
|
||
response = requests.post(
|
||
f"{BASE_URL}/tools/slots",
|
||
json={"bet": bet, "agent_id": agent_id},
|
||
timeout=5,
|
||
)
|
||
response.raise_for_status()
|
||
result = response.json()
|
||
if "error" in result:
|
||
st.error(f"Error: {result['error']}")
|
||
else:
|
||
st.write(f"**Result**: {result['explanation']}")
|
||
st.write(f"**Reels**: {result['game_state']['reels']}")
|
||
st.write(f"**Payout**: {result['payout']}")
|
||
st.write(f"**New Balance**: {result['new_balance']}")
|
||
except requests.RequestException as e:
|
||
st.error(f"Error: {str(e)}")
|
||
|
||
elif tool_id == "blackjack":
|
||
st.subheader("Blackjack")
|
||
agent_id = st.text_input(
|
||
"Your Agent ID", value="player1", key="blackjack_agent"
|
||
)
|
||
|
||
# Initialize session state for blackjack game ID
|
||
if "blackjack_game_id" not in st.session_state:
|
||
st.session_state.blackjack_game_id = None
|
||
logger.debug("Initialized blackjack_game_id as None in session state")
|
||
|
||
# Start a new game
|
||
if st.session_state.blackjack_game_id is None:
|
||
bet = st.number_input("Bet Amount", min_value=1, step=1, value=10)
|
||
if st.button("Start Game"):
|
||
logger.debug(
|
||
f"Starting blackjack with bet: {bet}, agent_id: {agent_id}"
|
||
)
|
||
try:
|
||
response = requests.post(
|
||
f"{BASE_URL}/tools/blackjack",
|
||
json={"bet": bet, "agent_id": agent_id},
|
||
timeout=5,
|
||
)
|
||
logger.debug(
|
||
f"POST /tools/blackjack status: {response.status_code}, content: {response.text}"
|
||
)
|
||
response.raise_for_status()
|
||
result = response.json()
|
||
if "error" in result:
|
||
st.error(f"Error: {result['error']}")
|
||
logger.error(f"Blackjack start error: {result['error']}")
|
||
else:
|
||
st.session_state.blackjack_game_id = result["game_id"]
|
||
logger.debug(
|
||
f"Set blackjack_game_id: {st.session_state.blackjack_game_id}"
|
||
)
|
||
st.write(f"**Game Started**: {result['explanation']}")
|
||
st.write(
|
||
f"**Your Hand**: {result['game_state']['player_hands'][0]} (Total: {result['game_state']['player_totals'][0]})"
|
||
)
|
||
st.write(
|
||
f"**Dealer’s Up Card**: {result['game_state']['dealer_hand']}"
|
||
)
|
||
st.rerun()
|
||
except requests.RequestException as e:
|
||
st.error(f"Error starting blackjack: {str(e)}")
|
||
logger.error(f"Error starting blackjack: {str(e)}", exc_info=True)
|
||
else:
|
||
# Display current game state and allow hit/stand/split
|
||
try:
|
||
response = requests.get(
|
||
f"{BASE_URL}/resources/casino/blackjack/games/{st.session_state.blackjack_game_id}",
|
||
timeout=5,
|
||
)
|
||
logger.debug(
|
||
f"GET /resources/.../{st.session_state.blackjack_game_id} status: {response.status_code}, content: {response.text}"
|
||
)
|
||
response.raise_for_status()
|
||
game_state = response.json()["content"]
|
||
st.write(
|
||
f"**Current Game (ID: {st.session_state.blackjack_game_id})**:"
|
||
)
|
||
for i, (hand, total) in enumerate(
|
||
zip(game_state["player_hands"], game_state["player_totals"])
|
||
):
|
||
active = (
|
||
" (Active)"
|
||
if i == game_state["active_hand"]
|
||
and game_state["status"] == "active"
|
||
else ""
|
||
)
|
||
st.write(f"**Hand {i + 1}{active}**: {hand} (Total: {total})")
|
||
st.write(f"**Dealer’s Up Card**: {game_state['dealer_hand']}")
|
||
st.write(f"**Total Bet**: {game_state['bet']}")
|
||
|
||
if game_state["status"] == "active":
|
||
col1, col2, col3 = st.columns(3)
|
||
with col1:
|
||
if st.button("Hit"):
|
||
logger.debug(
|
||
f"Sending hit action for game_id: {st.session_state.blackjack_game_id}"
|
||
)
|
||
try:
|
||
response = requests.post(
|
||
f"{BASE_URL}/tools/blackjack",
|
||
json={
|
||
"agent_id": agent_id,
|
||
"game_id": st.session_state.blackjack_game_id,
|
||
"action": "hit",
|
||
},
|
||
timeout=5,
|
||
)
|
||
logger.debug(
|
||
f"POST /tools/blackjack (hit) status: {response.status_code}, content: {response.text}"
|
||
)
|
||
response.raise_for_status()
|
||
result = response.json()
|
||
if "error" in result:
|
||
st.error(f"Error: {result['error']}")
|
||
logger.error(f"Hit error: {result['error']}")
|
||
else:
|
||
st.write(f"**Result**: {result['explanation']}")
|
||
if result["game_complete"]:
|
||
st.write(f"**Payout**: {result['payout']}")
|
||
st.write(
|
||
f"**New Balance**: {result['new_balance']}"
|
||
)
|
||
st.session_state.blackjack_game_id = None
|
||
logger.debug(
|
||
"Game completed, reset blackjack_game_id to None"
|
||
)
|
||
st.rerun()
|
||
except requests.RequestException as e:
|
||
st.error(f"Error during hit: {str(e)}")
|
||
logger.error(
|
||
f"Error during hit: {str(e)}", exc_info=True
|
||
)
|
||
with col2:
|
||
if st.button("Stand"):
|
||
logger.debug(
|
||
f"Sending stand action for game_id: {st.session_state.blackjack_game_id}"
|
||
)
|
||
try:
|
||
response = requests.post(
|
||
f"{BASE_URL}/tools/blackjack",
|
||
json={
|
||
"agent_id": agent_id,
|
||
"game_id": st.session_state.blackjack_game_id,
|
||
"action": "stand",
|
||
},
|
||
timeout=5,
|
||
)
|
||
logger.debug(
|
||
f"POST /tools/blackjack (stand) status: {response.status_code}, content: {response.text}"
|
||
)
|
||
response.raise_for_status()
|
||
result = response.json()
|
||
if "error" in result:
|
||
st.error(f"Error: {result['error']}")
|
||
logger.error(f"Stand error: {result['error']}")
|
||
else:
|
||
st.write(f"**Result**: {result['explanation']}")
|
||
if result["game_complete"]:
|
||
for outcome in result["outcomes"]:
|
||
if "win" in outcome.lower():
|
||
st.success(outcome)
|
||
elif "lose" in outcome.lower():
|
||
st.error(outcome)
|
||
else:
|
||
st.warning(outcome)
|
||
st.write(
|
||
f"**Total Payout**: {result['payout']}"
|
||
)
|
||
st.write(
|
||
f"**New Balance**: {result['new_balance']}"
|
||
)
|
||
st.session_state.blackjack_game_id = None
|
||
logger.debug(
|
||
"Game completed, reset blackjack_game_id to None"
|
||
)
|
||
st.rerun()
|
||
except requests.RequestException as e:
|
||
st.error(f"Error during stand: {str(e)}")
|
||
logger.error(
|
||
f"Error during stand: {str(e)}", exc_info=True
|
||
)
|
||
with col3:
|
||
can_split = (
|
||
len(game_state["player_hands"]) == 1
|
||
and len(game_state["player_hands"][0]) == 2
|
||
and game_state["player_hands"][0][0]
|
||
== game_state["player_hands"][0][1]
|
||
)
|
||
if can_split and st.button("Split"):
|
||
logger.debug(
|
||
f"Sending split action for game_id: {st.session_state.blackjack_game_id}"
|
||
)
|
||
try:
|
||
response = requests.post(
|
||
f"{BASE_URL}/tools/blackjack",
|
||
json={
|
||
"agent_id": agent_id,
|
||
"game_id": st.session_state.blackjack_game_id,
|
||
"action": "split",
|
||
},
|
||
timeout=5,
|
||
)
|
||
logger.debug(
|
||
f"POST /tools/blackjack (split) status: {response.status_code}, content: {response.text}"
|
||
)
|
||
response.raise_for_status()
|
||
result = response.json()
|
||
if "error" in result:
|
||
st.error(f"Error: {result['error']}")
|
||
logger.error(f"Split error: {result['error']}")
|
||
else:
|
||
st.write(f"**Result**: {result['explanation']}")
|
||
st.rerun()
|
||
except requests.RequestException as e:
|
||
st.error(f"Error during split: {str(e)}")
|
||
logger.error(
|
||
f"Error during split: {str(e)}", exc_info=True
|
||
)
|
||
except requests.RequestException as e:
|
||
st.error(f"Error fetching game state: {str(e)}")
|
||
logger.error(f"Error fetching game state: {str(e)}", exc_info=True)
|
||
st.session_state.blackjack_game_id = None
|
||
logger.debug("Reset blackjack_game_id to None due to fetch error")
|
||
|
||
|
||
def memory_interface():
|
||
st.header("Memory")
|
||
action = st.radio("Action", ["Store", "Retrieve", "List", "Delete"])
|
||
|
||
if action == "Store":
|
||
key = st.text_input("Key")
|
||
value = st.text_input("Value")
|
||
if st.button("Store"):
|
||
try:
|
||
response = requests.post(
|
||
f"{BASE_URL}/memory", json={"key": key, "value": value}, timeout=5
|
||
)
|
||
response.raise_for_status()
|
||
st.success("Stored successfully!")
|
||
list_response = requests.get(f"{BASE_URL}/memory", timeout=5)
|
||
list_response.raise_for_status()
|
||
keys = list_response.json()["keys"]
|
||
st.write("Current Memory Keys:", ", ".join(keys) if keys else "None")
|
||
except requests.RequestException as e:
|
||
st.error(f"Error: {str(e)}")
|
||
|
||
elif action == "Retrieve":
|
||
key = st.text_input("Key to retrieve")
|
||
if st.button("Retrieve"):
|
||
try:
|
||
response = requests.get(f"{BASE_URL}/memory/{key}", timeout=5)
|
||
response.raise_for_status()
|
||
value = response.json()["value"]
|
||
st.write(f"Value: {value if value is not None else 'Not found'}")
|
||
except requests.RequestException as e:
|
||
st.error(f"Error: {str(e)}")
|
||
|
||
elif action == "List":
|
||
if st.button("List All Keys"):
|
||
try:
|
||
response = requests.get(f"{BASE_URL}/memory", timeout=5)
|
||
response.raise_for_status()
|
||
keys = response.json()["keys"]
|
||
st.write("Memory Keys:", ", ".join(keys) if keys else "None")
|
||
except requests.RequestException as e:
|
||
st.error(f"Error: {str(e)}")
|
||
|
||
elif action == "Delete":
|
||
key = st.text_input("Key to delete")
|
||
if st.button("Delete"):
|
||
try:
|
||
response = requests.delete(f"{BASE_URL}/memory/{key}", timeout=5)
|
||
response.raise_for_status()
|
||
st.success("Deleted successfully!")
|
||
list_response = requests.get(f"{BASE_URL}/memory", timeout=5)
|
||
list_response.raise_for_status()
|
||
keys = list_response.json()["keys"]
|
||
st.write("Current Memory Keys:", ", ".join(keys) if keys else "None")
|
||
except requests.RequestException as e:
|
||
st.error(f"Error: {str(e)}")
|
||
|
||
|
||
def resources_interface():
|
||
st.header("Resources")
|
||
|
||
# Fetch available resources
|
||
try:
|
||
response = requests.get(f"{BASE_URL}/resources", timeout=5)
|
||
response.raise_for_status()
|
||
resources = response.json()["resources"]
|
||
except requests.RequestException as e:
|
||
st.warning(f"Could not fetch resources: {str(e)}")
|
||
resources = []
|
||
|
||
if not resources:
|
||
st.write("No resources available.")
|
||
return
|
||
|
||
# Select resource for GET
|
||
resource_id = st.selectbox("Select resource to get", [r["id"] for r in resources])
|
||
if st.button("Get Resource"):
|
||
try:
|
||
response = requests.get(f"{BASE_URL}/resources/{resource_id}", timeout=5)
|
||
response.raise_for_status()
|
||
result = response.json()
|
||
if "error" in result:
|
||
st.error(f"Error: {result['error']}")
|
||
elif "resources" in result: # Prefix search result
|
||
st.write("Nested Resources Found:")
|
||
for res in result["resources"]:
|
||
st.write(f"- **{res['id']}**: {res['content']}")
|
||
else: # Exact match
|
||
st.write(f"**{result['id']}**: {result['content']}")
|
||
except requests.RequestException as e:
|
||
st.error(f"Error: {str(e)}")
|
||
|
||
# Form for updating/creating a resource
|
||
st.subheader("Update or Create Resource")
|
||
with st.form(key="resource_form"):
|
||
new_resource_id = st.text_input("Resource ID", value=resource_id)
|
||
content = st.text_area("Content", height=100)
|
||
submit_button = st.form_submit_button(label="Update/Create", type="primary")
|
||
|
||
if submit_button and new_resource_id and content:
|
||
try:
|
||
response = requests.put(
|
||
f"{BASE_URL}/resources/{new_resource_id}",
|
||
json={"content": content},
|
||
timeout=5,
|
||
)
|
||
response.raise_for_status()
|
||
result = response.json()
|
||
st.success(
|
||
f"Resource {result['resource']['id']} updated/created successfully!"
|
||
)
|
||
st.write(
|
||
f"**{result['resource']['id']}**: {result['resource']['content']}"
|
||
)
|
||
except requests.RequestException as e:
|
||
st.error(f"Error: {str(e)}")
|
||
|
||
|
||
def pay_interface():
|
||
st.header("Pay")
|
||
amount = st.number_input("Amount", min_value=0.0, step=0.01)
|
||
if st.button("Pay"):
|
||
try:
|
||
response = requests.post(
|
||
f"{BASE_URL}/pay", json={"amount": amount}, timeout=5
|
||
)
|
||
response.raise_for_status()
|
||
st.write(f"Transaction ID: {response.json()['transaction_id']}")
|
||
st.write(f"Status: {response.json()['status']}")
|
||
except requests.RequestException as e:
|
||
st.error(f"Error: {str(e)}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|