Skip to content

Commit

Permalink
add customized dimensions
Browse files Browse the repository at this point in the history
  • Loading branch information
bugsz committed Dec 19, 2024
1 parent 9464ab3 commit 5079726
Show file tree
Hide file tree
Showing 8 changed files with 310 additions and 32 deletions.
39 changes: 34 additions & 5 deletions sotopia/ui/streamlit_ui/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
# st.session_state.API_BASE = f"http://localhost:{PORT}"
# st.session_state.WS_BASE = f"ws://localhost:{PORT}"

DEFAULT_BASE = "sotopia-lab--sotopia-fastapi-webapi-dev-serve.modal.run"

# Modal Configuration
st.session_state.API_BASE = (
"https://sotopia-lab--sotopia-fastapi-webapi-serve.modal.run"
)
st.session_state.WS_BASE = "ws://sotopia-lab--sotopia-fastapi-webapi-serve.modal.run"

if "API_BASE" not in st.session_state:
st.session_state.API_BASE = f"https://{DEFAULT_BASE}"
st.session_state.WS_BASE = f"ws://{DEFAULT_BASE}"


def update_database_callback() -> None:
Expand Down Expand Up @@ -52,7 +54,13 @@ def update_database_callback() -> None:
display_chat = st.Page(
f"{page_path}/render_chat_websocket.py",
title="Simulation",
icon=":material/add:",
# icon=":material/add:",
)

display_evaluation_dimensions = st.Page(
f"{page_path}/display_evaluation_dimensions.py",
title="Evaluation Dimensions",
# icon=":material/add:",
)

add_characters = st.Page(
Expand All @@ -75,6 +83,7 @@ def update_database_callback() -> None:
display_characters,
display_episodes,
display_chat,
display_evaluation_dimensions,
add_characters,
add_scenarios,
add_evaluation_dimensions,
Expand Down Expand Up @@ -105,5 +114,25 @@ def update_database_callback() -> None:
key="new_database_url",
)

with st.sidebar:
with st.expander("API Configuration", expanded=False):
st.session_state.API_BASE = st.text_input(
"API Base URL:",
value=st.session_state.API_BASE,
placeholder="Enter API base URL",
)

st.session_state.WS_BASE = st.text_input(
"WebSocket Base URL:",
value=st.session_state.WS_BASE,
placeholder="Enter WebSocket base URL",
)

# Optional: Add a reset button
if st.button("Reset to Default"):
st.session_state.API_BASE = f"https://{DEFAULT_BASE}"
st.session_state.WS_BASE = f"ws://{DEFAULT_BASE}"
st.rerun()


pg.run()
163 changes: 148 additions & 15 deletions sotopia/ui/streamlit_ui/pages/add_evaluation_dimension.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,161 @@ class CustomEvaluationDimensionsWrapper(BaseModel):
dimensions: list[CustomEvaluationDimension] = Field(
default=[], description="The dimensions of the custom evaluation dimension list"
)
class CustomEvaluationDimension(JsonModel):
name: str = Field(index=True)
description: str = Field(index=True)
range_high: int = Field(index=True)
range_low: int = Field(index=True)
"""

import streamlit as st
import requests
from sotopia.database import CustomEvaluationDimension
from sotopia.ui.fastapi_server import CustomEvaluationDimensionsWrapper
from sotopia.ui.streamlit_ui.rendering.get_elements import (
get_distinct_evaluation_dimensions,
)


def add_evaluation_dimension() -> None:
st.title("Add Evaluation Dimension")

with st.expander("Evaluation Dimension List", expanded=True):
st.text_input("Name", key="name_list")
st.text_input("Description", key="description_list")
st.text_input("Evaluation Dimension", key="evaluation_dimension_list")

with st.expander("Evaluation Dimension", expanded=True):
st.text_input("Name", key="name_list_item")
st.text_input("Description", key="description_list_item")
st.text_input("Evaluation Dimension", key="evaluation_dimension_list_item")
st.button(
"Add another Evaluation Dimension", key="add_another_evaluation_dimension"
)
st.title("Add Evaluation Dimensions")

# Initialize session state for dimensions list if it doesn't exist
if "dimensions" not in st.session_state:
st.session_state.dimensions = []

# Get existing dimensions
existing_dimensions = get_distinct_evaluation_dimensions()

# Tab-based interface for adding dimensions
tab1, tab2 = st.tabs(["Add New Dimension", "Select Existing Dimension"])

# Tab 1: Add New Dimension
with tab1:
with st.form(key="add_dimension_form"):
st.subheader("Add New Dimension")
dim_name = st.text_input("Dimension Name")
dim_description = st.text_area("Dimension Description")
col1, col2 = st.columns(2)
with col1:
range_low = st.number_input("Range Low", value=0)
with col2:
range_high = st.number_input("Range High", value=10)

add_dimension = st.form_submit_button("Add Dimension")

if add_dimension and dim_name and dim_description:
new_dimension = CustomEvaluationDimension(
name=dim_name,
description=dim_description,
range_low=range_low,
range_high=range_high,
)
st.session_state.dimensions.append(new_dimension)
st.success(f"Added dimension: {dim_name}")
st.rerun()

# Tab 2: Select Existing Dimension
with tab2:
with st.form(key="select_dimension_form"):
st.subheader("Select Existing Dimension")

# Create a list of dimension names for the selectbox
dimension_options = [
f"{dim.name} (Range: [{dim.range_low}, {dim.range_high}])"
for dim in existing_dimensions
]

if dimension_options:
selected_dimension = st.selectbox(
"Choose a dimension",
options=dimension_options,
format_func=lambda x: x.split(" (Range")[
0
], # Show only the name in the dropdown
)

# Show details of selected dimension
if selected_dimension:
selected_idx = dimension_options.index(selected_dimension)
dim = existing_dimensions[selected_idx]
st.info(f"Description: {dim.description}")

add_existing = st.form_submit_button("Add Selected Dimension")

if add_existing:
selected_idx = dimension_options.index(selected_dimension)
dim_to_add = existing_dimensions[selected_idx]

# Check if dimension already exists in current list
if any(
d.name == dim_to_add.name for d in st.session_state.dimensions
):
st.error(
f"Dimension '{dim_to_add.name}' already exists in the list"
)
else:
st.session_state.dimensions.append(dim_to_add)
st.success(f"Added existing dimension: {dim_to_add.name}")
st.rerun()
else:
st.warning("No existing dimensions available")

# Display current dimensions with delete buttons
if st.session_state.dimensions:
st.subheader("Current Dimensions")
for idx, dim in enumerate(st.session_state.dimensions):
col1, col2, col3 = st.columns([3, 1, 0.5])
with col1:
with st.expander(f"Dimension {idx + 1}: {dim.name}", expanded=False):
st.write(f"Description: {dim.description}")
st.write(f"Range: {dim.range_low} - {dim.range_high}")
with col2:
if st.button("Delete", key=f"delete_{idx}"):
st.session_state.dimensions.pop(idx)
st.success(f"Deleted dimension: {dim.name}")
st.rerun()
with col3:
st.write("") # Spacer

# Submit form at the bottom
with st.form(key="submit_form"):
st.subheader("Submit Evaluation Dimension List")
list_name = st.text_input("List Name")

col1, col2 = st.columns(2)
with col1:
submit_button = st.form_submit_button("Submit All")
with col2:
clear_button = st.form_submit_button("Clear All")

if submit_button and list_name:
try:
wrapper = CustomEvaluationDimensionsWrapper(
name=list_name, dimensions=st.session_state.dimensions
)
# st.write(wrapper.dict())

response = requests.post(
f"{st.session_state.API_BASE}/evaluation_dimensions/",
json=wrapper.dict(),
)

if response.status_code == 200:
st.success("Successfully created evaluation dimension list!")
# st.session_state.dimensions = []
# st.rerun()
else:
st.error(f"Error: {response.json()['detail']}")

except Exception as e:
st.error(f"An error occurred: {str(e)}")

st.button("Add Evaluation Dimension", key="add_evaluation_dimension")
if clear_button:
st.session_state.dimensions = []
st.rerun()


add_evaluation_dimension()
48 changes: 48 additions & 0 deletions sotopia/ui/streamlit_ui/pages/display_evaluation_dimensions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import streamlit as st

from sotopia.database import CustomEvaluationDimension

from sotopia.ui.streamlit_ui.rendering import (
get_evaluation_dimensions,
render_evaluation_dimension,
get_distinct_evaluation_dimensions,
render_evaluation_dimension_list,
)

st.title("Evaluation Dimensions")

st.write("Here are some instructions about using the evaluation dimension renderer.")


def display_evaluation_dimensions() -> None:
# st.title("Evaluation Dimensions")
distinct_dimensions: list[CustomEvaluationDimension] = (
get_distinct_evaluation_dimensions()
)

# sort the dimensions by name
distinct_dimensions.sort(key=lambda x: x.name)

with st.expander("Evaluation Dimensions", expanded=True):
all_dimensions = []
col1, col2 = st.columns(2, gap="medium")
for i, dimension in enumerate(distinct_dimensions):
with col1 if i % 2 == 0 else col2:
render_evaluation_dimension(dimension)

with st.expander("Evaluation Dimension Lists", expanded=True):
all_dimension_lists: dict[str, list[CustomEvaluationDimension]] = (
get_evaluation_dimensions()
)
col1, col2 = st.columns(2, gap="medium")
for i, (dimension_list_name, dimensions) in enumerate(
all_dimension_lists.items()
):
all_dimensions: list[CustomEvaluationDimension] = [
CustomEvaluationDimension(**dimension) for dimension in dimensions
]
with col1 if i % 2 == 0 else col2:
render_evaluation_dimension_list(dimension_list_name, all_dimensions)


display_evaluation_dimensions()
1 change: 1 addition & 0 deletions sotopia/ui/streamlit_ui/pages/intro.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@
- Also see [Sotopia examples](https://github.com/sotopia-lab/sotopia/example) for more information.
"""
)
st.markdown("Current API Base: " + st.session_state.API_BASE)
22 changes: 11 additions & 11 deletions sotopia/ui/streamlit_ui/pages/render_chat_websocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,17 +273,6 @@ def chat_demo() -> None:
unsafe_allow_html=True,
)

evaluation_dimension_str = f"**Evaluation Dimensions:** {st.session_state.evaluation_dimension_choice}, including<br>"
for eval_dim in st.session_state.evaluation_dimension_dict[
st.session_state.evaluation_dimension_choice
]:
evaluation_dimension_str += f"{eval_dim['name']}, "

st.markdown(
evaluation_dimension_str[:-2] + ".",
unsafe_allow_html=True,
)

agent1_col, agent2_col = st.columns(2)
with agent1_col:
st.selectbox(
Expand Down Expand Up @@ -325,6 +314,17 @@ def chat_demo() -> None:
disabled=is_active(),
)

evaluation_dimension_str = f"**Evaluation Dimensions:** {st.session_state.evaluation_dimension_choice}. <br>**Metric includes:** "
for eval_dim in st.session_state.evaluation_dimension_dict[
st.session_state.evaluation_dimension_choice
]:
evaluation_dimension_str += f"{eval_dim['name']}, "

st.markdown(
evaluation_dimension_str[:-2] + ".",
unsafe_allow_html=True,
)

with st.expander("Other Options", expanded=False):
st.text_input("Max Turns", key="max_turns", value="20")
st.text_input("Max Stale Turns", key="max_stale_turns", value="3")
Expand Down
6 changes: 6 additions & 0 deletions sotopia/ui/streamlit_ui/rendering/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
render_environment_profile,
render_conversation_and_evaluation,
render_character,
render_evaluation_dimension,
render_evaluation_dimension_list,
)
from .render_utils import (
avatar_mapping,
Expand All @@ -16,6 +18,7 @@
get_agents,
get_models,
get_evaluation_dimensions,
get_distinct_evaluation_dimensions,
)

__all__ = [
Expand All @@ -31,4 +34,7 @@
"get_agents",
"get_models",
"get_evaluation_dimensions",
"get_distinct_evaluation_dimensions",
"render_evaluation_dimension",
"render_evaluation_dimension_list",
]
16 changes: 16 additions & 0 deletions sotopia/ui/streamlit_ui/rendering/get_elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import streamlit as st
from typing import Any
from sotopia.ui.streamlit_ui.rendering.render_utils import get_full_name
from sotopia.database import CustomEvaluationDimension


def get_models() -> dict[str, dict[Any, Any]]:
Expand Down Expand Up @@ -35,3 +36,18 @@ def get_evaluation_dimensions() -> dict[str, dict[Any, Any]]:
evaluation_dimensions = resp.json()

return evaluation_dimensions


def get_distinct_evaluation_dimensions() -> list[CustomEvaluationDimension]:
all_dimension_lists: dict[str, list[Any]] = get_evaluation_dimensions()
distinct_dimensions: list[CustomEvaluationDimension] = []
distinct_dimension_names: set[str] = set()

for dimension_list_name, dimensions in all_dimension_lists.items():
for dimension in dimensions:
custom_dimension = CustomEvaluationDimension(**dimension)
if custom_dimension.name not in distinct_dimension_names:
distinct_dimensions.append(custom_dimension)
distinct_dimension_names.add(custom_dimension.name)

return distinct_dimensions
Loading

0 comments on commit 5079726

Please sign in to comment.