-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/sotopia demo UI #261
Merged
Merged
Changes from 13 commits
Commits
Show all changes
67 commits
Select commit
Hold shift + click to select a range
a693fe2
initial
XuhuiZhou b2c422e
initial ui
XuhuiZhou df5f989
Merge branch 'main' into feature/sotopia-demo-ui
XuhuiZhou 950830c
merge main
XuhuiZhou 71483d9
add new ui
XuhuiZhou 2e2514f
switch to fastAPI
XuhuiZhou e8fff7b
websocket check
XuhuiZhou 878eb88
Merge branch 'demo' into feature/sotopia-demo-ui
XuhuiZhou 79e9986
fix render episode error
XuhuiZhou f29f7f7
add page; make a simplified page and still WIP
bugsz 99b58ba
[autofix.ci] apply automated fixes
autofix-ci[bot] 3cc6dc0
fix simplified streaming version
bugsz 4b54e44
semi-done character page + avatar assets
astrophie f77e302
Fixed character card styling
astrophie 380b94c
[autofix.ci] apply automated fixes
autofix-ci[bot] 756a749
unified rendering and chat display
bugsz 02c76da
Merge branch 'feature/sotopia-demo-ui' of https://github.com/sotopia-β¦
bugsz 3f7214e
updated chat character icons
astrophie d9b6204
add some tags
XuhuiZhou ceaabde
Merge branch 'feature/sotopia-demo-ui' of github.com:sotopia-lab/sotoβ¦
XuhuiZhou 871fc1f
add typing
XuhuiZhou b372f2f
temp fix
XuhuiZhou 69888db
add characters avatar to simulation
XuhuiZhou 9764c34
fix episode full avatar
XuhuiZhou 57dc305
go to modal config
XuhuiZhou dca51a9
clean up code
bugsz d15fd83
manually merge branch
bugsz fa625be
add modal streamlit app
bugsz 9ba63f9
clean codebase except websocket
XuhuiZhou c7850bb
remove repeated local css
XuhuiZhou 6384eb6
clean websocket
XuhuiZhou 7aa64ec
fix get name error
XuhuiZhou 5b48f30
fix errors
XuhuiZhou 563af64
pre render scenario
XuhuiZhou 1d743c0
add custom eval
XuhuiZhou 9e3651b
Merge branch 'demo' into feature/sotopia-demo-ui
XuhuiZhou cb54051
change streamlit to dynamic path
bugsz e2575ea
new uv
XuhuiZhou 116fa77
revert to previous install commands
bugsz d3c987b
Merge branch 'feature/sotopia-demo-ui' of https://github.com/sotopia-β¦
bugsz f64e715
a fix for modal
XuhuiZhou eccba6a
add customized dimension
bugsz a1c1de1
Merge branch 'feature/sotopia-demo-ui' of https://github.com/sotopia-β¦
bugsz 1810999
[autofix.ci] apply automated fixes
autofix-ci[bot] f4eee2d
sort scenarios in simulation
bugsz aa8f1bb
Merge branch 'feature/sotopia-demo-ui' of https://github.com/sotopia-β¦
bugsz ed5168e
for demo video
XuhuiZhou 0b12ccd
update deploy instruction
bugsz 1069f6c
update intro page
bugsz 466b6f9
update intro page
bugsz 733074d
[autofix.ci] apply automated fixes
autofix-ci[bot] e3a7651
update intro page
bugsz 9464ab3
Merge branch 'feature/sotopia-demo-ui' of https://github.com/sotopia-β¦
bugsz 5079726
add customized dimensions
bugsz 79aa67f
update api link and modal environment
bugsz 88a80a3
move folder
XuhuiZhou eb3700d
fix relative import
XuhuiZhou e144682
update modal image build
bugsz b6c703b
Merge branch 'feature/sotopia-demo-ui' of https://github.com/sotopia-β¦
bugsz 6d0ae1f
use uv to build environment
bugsz 9ef75c4
change folder name
XuhuiZhou 69d1124
Merge branch 'demo' into feature/sotopia-demo-ui
XuhuiZhou f8d9c0f
change test
XuhuiZhou f55e183
fix modal serve
XuhuiZhou 3917d7b
environment change
XuhuiZhou 6e620d6
refactor
XuhuiZhou 5219d40
fix ui
XuhuiZhou File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
[theme] | ||
base="light" | ||
primaryColor = "#26184e" | ||
backgroundColor="#FFFFFF" | ||
secondaryBackgroundColor="#F0F2F6" | ||
textColor="#31333F" | ||
font="sans serif" | ||
|
||
|
||
[server] | ||
enableStaticServing = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from .utils import reset_database | ||
from .rendering.rendering_utils import ( | ||
_agent_profile_to_friendabove_self, | ||
render_for_humans, | ||
) | ||
|
||
__all__ = ["reset_database", "_agent_profile_to_friendabove_self", "render_for_humans"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import os | ||
|
||
import streamlit as st | ||
|
||
from sotopia.ui.streamlit_ui.utils import reset_database | ||
|
||
PORT = 8800 | ||
st.session_state.API_BASE = f"http://localhost:{PORT}" | ||
st.session_state.WS_BASE = f"ws://localhost:{PORT}" | ||
|
||
|
||
def update_database_callback() -> None: | ||
new_database_url = st.session_state.new_database_url | ||
updated_url = ( | ||
new_database_url if new_database_url != "" else st.session_state.DEFAULT_DB_URL | ||
) | ||
try: | ||
reset_database(updated_url) | ||
except Exception as e: | ||
st.error(f"Error occurred while updating database: {e}, please try again.") | ||
|
||
st.session_state.current_database_url = updated_url | ||
print("Updated DB URL: ", st.session_state.current_database_url) | ||
|
||
|
||
# Page Configuration | ||
st.set_page_config(page_title="SocialStream_Demo", page_icon="π§", layout="wide") | ||
|
||
display_intro = st.Page( | ||
"./pages/intro.py", title="Introduction", icon=":material/home:" | ||
) | ||
display_episodes = st.Page( | ||
"./pages/display_episodes.py", title="Episode", icon=":material/photo_library:" | ||
) | ||
display_scenarios = st.Page( | ||
"./pages/display_scenarios.py", | ||
title="Scenarios", | ||
icon=":material/insert_drive_file:", | ||
) | ||
display_characters = st.Page( | ||
"./pages/display_characters.py", title="Characters", icon=":material/people:" | ||
) | ||
|
||
display_chat = st.Page( | ||
"./pages/render_chat_websocket_simplified.py", | ||
title="Simulation", | ||
icon=":material/add:", | ||
) | ||
|
||
add_characters = st.Page( | ||
"./pages/add_characters.py", title="Add Characters", icon=":material/add:" | ||
) | ||
|
||
add_scenarios = st.Page( | ||
"./pages/add_scenarios.py", title="Add Scenarios", icon=":material/add:" | ||
) | ||
|
||
pg = st.navigation( | ||
[ | ||
display_intro, | ||
display_scenarios, | ||
display_episodes, | ||
display_characters, | ||
display_chat, | ||
add_characters, | ||
add_scenarios, | ||
] | ||
) | ||
|
||
# Reset active agent when switching modes across pages | ||
if "mode" not in st.session_state or pg.title != st.session_state.get("mode", None): | ||
if "active" in st.session_state: | ||
del st.session_state["active"] | ||
# print("Active agent reset.") | ||
|
||
st.session_state.mode = pg.title | ||
|
||
|
||
# DB URL Configuration | ||
if "DEFAULT_DB_URL" not in st.session_state: | ||
st.session_state.DEFAULT_DB_URL = os.environ.get("REDIS_OM_URL", "") | ||
st.session_state.current_database_url = st.session_state.DEFAULT_DB_URL | ||
print("Default DB URL: ", st.session_state.DEFAULT_DB_URL) | ||
|
||
# impl 2: popup update URL | ||
with st.sidebar.popover("(Optional) Enter Database URL"): | ||
new_database_url = st.text_input( | ||
"URL: (starting in redis://)", | ||
value="", | ||
on_change=update_database_callback, | ||
key="new_database_url", | ||
) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We also need to have a fastAPI for this? |
||
|
||
|
||
pg.run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
.truncate{ | ||
max-height: 2em; | ||
text-overflow: ellipsis; | ||
margin-bottom: 12px; | ||
cursor: pointer; | ||
word-break: break-all; | ||
overflow:hidden; | ||
white-space: nowrap; | ||
transition: max-height 1s, white-space 1s; | ||
} | ||
.truncate:hover{ | ||
overflow: auto; | ||
overflow-y: scroll; | ||
white-space: normal; | ||
max-height: 200px; | ||
} | ||
/* | ||
[data-testid="stAppViewContainer"] { | ||
background-image: url("https://images.unsplash.com/photo-1729096532452-50549f2bb63c"); | ||
background-size: 40%; | ||
background-position: top right; | ||
background-repeat: no-repeat; | ||
background-attachment: local; | ||
} */ | ||
|
||
[data-testid="stHeader"] { | ||
background: rgba(0,0,0,0); | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
""" | ||
Definition | ||
@app.post("/agents/", response_model=str) | ||
async def create_agent(agent: AgentProfileWrapper) -> str: | ||
agent_profile = AgentProfile(**agent.model_dump()) | ||
agent_profile.save() | ||
pk = agent_profile.pk | ||
assert pk is not None | ||
return pk | ||
|
||
class AgentProfileWrapper(BaseModel): | ||
Wrapper for AgentProfile to avoid pydantic v2 issues | ||
|
||
first_name: str | ||
last_name: str | ||
age: int = 0 | ||
occupation: str = "" | ||
gender: str = "" | ||
gender_pronoun: str = "" | ||
public_info: str = "" | ||
big_five: str = "" | ||
moral_values: list[str] = [] | ||
schwartz_personal_values: list[str] = [] | ||
personality_and_values: str = "" | ||
decision_making_style: str = "" | ||
secret: str = "" | ||
model_id: str = "" | ||
mbti: str = "" | ||
tag: str = "" | ||
""" | ||
|
||
import streamlit as st | ||
import requests | ||
|
||
from sotopia.ui.fastapi_server import AgentProfileWrapper | ||
# add fields for agent profiles | ||
|
||
|
||
def local_css(file_name: str) -> None: | ||
with open(file_name) as f: | ||
st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True) | ||
|
||
|
||
def rendering_character_form() -> None: | ||
local_css("././css/style.css") | ||
st.markdown("<h1>Character Creation</h1>", unsafe_allow_html=True) | ||
st.write("Fill in the fields below to create a new character:") | ||
|
||
first_name = st.text_input("First Name") | ||
last_name = st.text_input("Last Name") | ||
age = st.number_input("Age", min_value=0) | ||
occupation = st.text_input("Occupation") | ||
gender = st.text_input("Gender") | ||
gender_pronoun = st.text_input("Gender Pronoun") | ||
public_info = st.text_area("Public Info") | ||
|
||
if st.button("Create Character"): | ||
agent_profile = AgentProfileWrapper( | ||
first_name=first_name, | ||
last_name=last_name, | ||
age=age, | ||
occupation=occupation, | ||
gender=gender, | ||
gender_pronoun=gender_pronoun, | ||
public_info=public_info, | ||
) | ||
print(agent_profile) | ||
|
||
response = requests.post( | ||
f"{st.session_state.API_BASE}/agents/", | ||
json=agent_profile.model_dump(), | ||
) | ||
|
||
if response.status_code != 200: | ||
st.error("Failed to create character. Error message: " + response.text) | ||
|
||
else: | ||
agent_id = response.json() | ||
st.success("Character created successfully! ID: " + agent_id) | ||
retrieved_agent = requests.get( | ||
f"{st.session_state.API_BASE}/agents/id/{agent_id}" | ||
) | ||
st.write(retrieved_agent.json()) | ||
|
||
|
||
rendering_character_form() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
""" | ||
Definition | ||
@app.post("/scenarios/", response_model=str) | ||
async def create_scenario(scenario: EnvironmentProfileWrapper) -> str: | ||
scenario_profile = EnvironmentProfile(**scenario.model_dump()) | ||
scenario_profile.save() | ||
pk = scenario_profile.pk | ||
assert pk is not None | ||
return pk | ||
|
||
class EnvironmentProfileWrapper(BaseModel): | ||
Wrapper for EnvironmentProfile to avoid pydantic v2 issues | ||
|
||
codename: str | ||
source: str = "" | ||
scenario: str = "" | ||
agent_goals: list[str] = [] | ||
relationship: Literal[0, 1, 2, 3, 4, 5] = 0 | ||
age_constraint: str | None = None | ||
occupation_constraint: str | None = None | ||
agent_constraint: list[list[str]] | None = None | ||
tag: str = "" | ||
|
||
class RelationshipType(IntEnum): | ||
stranger = 0 | ||
know_by_name = 1 | ||
acquaintance = 2 | ||
friend = 3 | ||
romantic_relationship = 4 | ||
family_member = 5 | ||
|
||
The age constraint of the environment, a list of tuples, each tuple is a range of age, e.g., '[(18, 25), (30, 40)]' | ||
means the environment is only available to agent one between 18 and 25, and agent two between 30 and 40 | ||
""" | ||
|
||
import streamlit as st | ||
from sotopia.ui.fastapi_server import EnvironmentProfileWrapper | ||
from sotopia.database import RelationshipType | ||
import requests | ||
|
||
|
||
def local_css(file_name: str) -> None: | ||
with open(file_name) as f: | ||
st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True) | ||
|
||
|
||
def rendering_scenario_form() -> None: | ||
bugsz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
local_css("././css/style.css") | ||
st.markdown("<h1>Scenario Creation</h1>", unsafe_allow_html=True) | ||
|
||
codename = st.text_input("Codename") | ||
source = st.text_input("Source") | ||
scenario = st.text_area("Scenario") | ||
# present relationship type with the descriptions, only accept one choice, then map to the enum | ||
relationship_mapping = { | ||
"Stranger": RelationshipType.stranger, | ||
"Know by Name": RelationshipType.know_by_name, | ||
"Acquaintance": RelationshipType.acquaintance, | ||
"Friend": RelationshipType.friend, | ||
"Romantic Relationship": RelationshipType.romantic_relationship, | ||
"Family Member": RelationshipType.family_member, | ||
} | ||
|
||
selected_relationship = st.selectbox( | ||
"Relationship", | ||
list(relationship_mapping.keys()), | ||
) | ||
relationship = relationship_mapping[selected_relationship] | ||
|
||
# first choose whether to use age constraint and then choose age range | ||
use_age_constraint = st.checkbox("Use Age Constraint") | ||
if use_age_constraint: | ||
min_age = st.number_input("Min Age", min_value=0, max_value=100) | ||
max_age = st.number_input("Max Age", min_value=0, max_value=100) | ||
age_constraint = f"[({min_age}, {max_age})]" | ||
if min_age > max_age: | ||
st.error("Min age cannot be greater than max age") | ||
else: | ||
age_constraint = None | ||
|
||
# first choose whether to use occupation constraint and then choose occupation | ||
use_occupation_constraint = st.checkbox( | ||
"Use Occupation Constraint, use comma to separate multiple occupations" | ||
) | ||
if use_occupation_constraint: | ||
occupation = st.text_input("Occupation") | ||
occupation_constraint = f"[{occupation}]" | ||
else: | ||
occupation_constraint = None | ||
|
||
agent1_goal = st.text_input("Agent 1 Goal") | ||
agent2_goal = st.text_input("Agent 2 Goal") | ||
|
||
if st.button("Create Scenario"): | ||
scenario_profile = EnvironmentProfileWrapper( | ||
codename=codename, | ||
source=source, | ||
scenario=scenario, | ||
relationship=relationship, | ||
age_constraint=age_constraint, | ||
occupation_constraint=occupation_constraint, | ||
agent_goals=[agent1_goal, agent2_goal], | ||
) | ||
|
||
response = requests.post( | ||
f"{st.session_state.API_BASE}/scenarios/", | ||
json=scenario_profile.model_dump(), | ||
) | ||
|
||
if response.status_code != 200: | ||
st.error("Failed to create scenario. Error: " + response.text) | ||
else: | ||
# there are quotes in the response | ||
scenario_id = response.json() | ||
|
||
st.success("Scenario created successfully! Scenario ID: " + scenario_id) | ||
retrieved_scenario = requests.get( | ||
f"{st.session_state.API_BASE}/scenarios/id/{scenario_id}" | ||
) | ||
st.write(retrieved_scenario.json()) | ||
|
||
|
||
rendering_scenario_form() |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we use AIOHTTP instead? therefore we don't need new package
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure about this. When I tried to host the websocket api it prompts me "No supported WebSocket library detected. Please use "pip install 'uvicorn[standard]'", or install 'websockets' or 'wsproto' manually."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, let's not worry about that for now