Skip to content
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

Adds multiple choice message handling to MesopUI #198

Merged
merged 9 commits into from
Sep 13, 2024
Merged
4 changes: 3 additions & 1 deletion docs/docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,17 +256,19 @@ search:
- [header](api/fastagency/ui/mesop/components/ui_common/header.md)
- data_model
- [Conversation](api/fastagency/ui/mesop/data_model/Conversation.md)
- [ConversationMessage](api/fastagency/ui/mesop/data_model/ConversationMessage.md)
- [State](api/fastagency/ui/mesop/data_model/State.md)
- main
- [conversation_box](api/fastagency/ui/mesop/main/conversation_box.md)
- [conversation_starter_box](api/fastagency/ui/mesop/main/conversation_starter_box.md)
- [get_ui](api/fastagency/ui/mesop/main/get_ui.md)
- [home_page](api/fastagency/ui/mesop/main/home_page.md)
- [on_user_feedback](api/fastagency/ui/mesop/main/on_user_feedback.md)
- [past_conversations_box](api/fastagency/ui/mesop/main/past_conversations_box.md)
- [send_prompt](api/fastagency/ui/mesop/main/send_prompt.md)
- message
- [MesopGUIMessageVisitor](api/fastagency/ui/mesop/message/MesopGUIMessageVisitor.md)
- [consume_responses](api/fastagency/ui/mesop/message/consume_responses.md)
- [handle_message](api/fastagency/ui/mesop/message/handle_message.md)
- [message_box](api/fastagency/ui/mesop/message/message_box.md)
- send_prompt
- [send_prompt_to_autogen](api/fastagency/ui/mesop/send_prompt/send_prompt_to_autogen.md)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
# 0.5 - API
# 2 - Release
# 3 - Contributing
# 5 - Template Page
# 10 - Default
search:
boost: 0.5
---

::: fastagency.ui.mesop.data_model.ConversationMessage
11 changes: 11 additions & 0 deletions docs/docs/en/api/fastagency/ui/mesop/message/consume_responses.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
# 0.5 - API
# 2 - Release
# 3 - Contributing
# 5 - Template Page
# 10 - Default
search:
boost: 0.5
---

::: fastagency.ui.mesop.message.consume_responses
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ search:
boost: 0.5
---

::: fastagency.ui.mesop.main.on_user_feedback
::: fastagency.ui.mesop.message.handle_message
4 changes: 2 additions & 2 deletions docs/docs_src/user_guide/custom_user_interactions/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
wf = AutoGenWorkflows()


@wf.register(name="exam_practice", description="Student and teacher chat") # type: ignore[type-var]
def exam_learning(ui: UI, initial_message: str, session_id: str) -> Optional[str]:
@wf.register(name="exam_practice", description="Student and teacher chat")
def exam_learning(ui: UI, initial_message: str, session_id: str) -> str:

Check warning on line 27 in docs/docs_src/user_guide/custom_user_interactions/main.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main.py#L26-L27

Added lines #L26 - L27 were not covered by tests

def is_termination_msg(msg: dict[str, Any]) -> bool:
return msg["content"] is not None and "TERMINATE" in msg["content"]
Expand Down
136 changes: 136 additions & 0 deletions docs/docs_src/user_guide/custom_user_interactions/main_mesop.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import os
from typing import Annotated, Any, Dict, Optional

from autogen import register_function
from autogen.agentchat import ConversableAgent

from fastagency import FastAgency
from fastagency import UI
from fastagency.base import MultipleChoice, SystemMessage, TextInput
from fastagency.ui.mesop import MesopUI
from fastagency.runtime.autogen.base import AutoGenWorkflows

llm_config = {

Check warning on line 13 in docs/docs_src/user_guide/custom_user_interactions/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main_mesop.py#L13

Added line #L13 was not covered by tests
"config_list": [
{
"model": "gpt-4o-mini",
"api_key": os.getenv("OPENAI_API_KEY"),
}
],
"temperature": 0.0,
}

wf = AutoGenWorkflows()

Check warning on line 23 in docs/docs_src/user_guide/custom_user_interactions/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main_mesop.py#L23

Added line #L23 was not covered by tests


@wf.register(name="exam_practice", description="Student and teacher chat")
def exam_learning(ui: UI, initial_message: str, session_id: str) -> str:

Check warning on line 27 in docs/docs_src/user_guide/custom_user_interactions/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main_mesop.py#L26-L27

Added lines #L26 - L27 were not covered by tests

def is_termination_msg(msg: dict[str, Any]) -> bool:
return msg["content"] is not None and "TERMINATE" in msg["content"]

Check warning on line 30 in docs/docs_src/user_guide/custom_user_interactions/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main_mesop.py#L29-L30

Added lines #L29 - L30 were not covered by tests

student_agent = ConversableAgent(

Check warning on line 32 in docs/docs_src/user_guide/custom_user_interactions/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main_mesop.py#L32

Added line #L32 was not covered by tests
name="Student_Agent",
system_message="You are a student writing a practice test. Your task is as follows:\n"
" 1) Retrieve exam questions by calling a function.\n"
" 2) Write a draft of proposed answers and engage in dialogue with your tutor.\n"
" 3) Once you are done with the dialogue, register the final answers by calling a function.\n"
" 4) Retrieve the final grade by calling a function.\n"
"Finally, terminate the chat by saying 'TERMINATE'.",
llm_config=llm_config,
human_input_mode="NEVER",
is_termination_msg=is_termination_msg,
)
teacher_agent = ConversableAgent(

Check warning on line 44 in docs/docs_src/user_guide/custom_user_interactions/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main_mesop.py#L44

Added line #L44 was not covered by tests
name="Teacher_Agent",
system_message="You are a teacher.",
llm_config=llm_config,
human_input_mode="NEVER",
is_termination_msg=is_termination_msg,
)

def retrieve_exam_questions(

Check warning on line 52 in docs/docs_src/user_guide/custom_user_interactions/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main_mesop.py#L52

Added line #L52 was not covered by tests
message: Annotated[str, "Message for examiner"]
) -> Optional[str]:
try:
msg = MultipleChoice(

Check warning on line 56 in docs/docs_src/user_guide/custom_user_interactions/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main_mesop.py#L55-L56

Added lines #L55 - L56 were not covered by tests
sender="student",
recipient="teacher",
prompt=message,
choices=[
"1) Mona Lisa",
"2) Innovations",
"3) Florence at the time of Leonardo",
"4) The Last Supper",
"5) Vitruvian Man",
],
default="1) Mona Lisa"
)
return ui.process_message(msg)
except Exception as e:
return f"retrieve_exam_questions() FAILED! {e}"

Check warning on line 71 in docs/docs_src/user_guide/custom_user_interactions/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main_mesop.py#L69-L71

Added lines #L69 - L71 were not covered by tests

def write_final_answers(message: Annotated[str, "Message for examiner"]) -> str:
try:
msg = SystemMessage(

Check warning on line 75 in docs/docs_src/user_guide/custom_user_interactions/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main_mesop.py#L73-L75

Added lines #L73 - L75 were not covered by tests
sender="function call logger",
recipient="system",
message={
"operation": "storing final answers",
"content": message,
},
)
ui.process_message(msg)
return "Final answers stored."
except Exception as e:
return f"write_final_answers() FAILED! {e}"

Check warning on line 86 in docs/docs_src/user_guide/custom_user_interactions/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main_mesop.py#L83-L86

Added lines #L83 - L86 were not covered by tests

def get_final_grade(

Check warning on line 88 in docs/docs_src/user_guide/custom_user_interactions/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main_mesop.py#L88

Added line #L88 was not covered by tests
message: Annotated[str, "Message for examiner"]
) -> Optional[str]:
try:
msg = MultipleChoice(

Check warning on line 92 in docs/docs_src/user_guide/custom_user_interactions/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main_mesop.py#L91-L92

Added lines #L91 - L92 were not covered by tests
sender="student",
recipient="teacher",
prompt=message,
choices=["A", "B", "C", "D", "F"],
)
return ui.process_message(msg)
except Exception as e:
return f"get_final_grade() FAILED! {e}"

Check warning on line 100 in docs/docs_src/user_guide/custom_user_interactions/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main_mesop.py#L98-L100

Added lines #L98 - L100 were not covered by tests

register_function(
retrieve_exam_questions,
caller=student_agent,
executor=teacher_agent,
name="retrieve_exam_questions",
description="Get exam questions from examiner",
)

register_function(

Check warning on line 110 in docs/docs_src/user_guide/custom_user_interactions/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main_mesop.py#L110

Added line #L110 was not covered by tests
write_final_answers,
caller=student_agent,
executor=teacher_agent,
name="write_final_answers",
description="Write a final answers to exam questions to examiner, but only after discussing with the tutor first.",
)

register_function(

Check warning on line 118 in docs/docs_src/user_guide/custom_user_interactions/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main_mesop.py#L118

Added line #L118 was not covered by tests
get_final_grade,
caller=student_agent,
executor=teacher_agent,
name="get_final_grade",
description="Get the final grade after submitting the answers.",
)

chat_result = teacher_agent.initiate_chat(

Check warning on line 126 in docs/docs_src/user_guide/custom_user_interactions/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main_mesop.py#L126

Added line #L126 was not covered by tests
student_agent,
message=initial_message,
summary_method="reflection_with_llm",
max_turns=10,
)

return chat_result.summary # type: ignore[no-any-return]

Check warning on line 133 in docs/docs_src/user_guide/custom_user_interactions/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main_mesop.py#L133

Added line #L133 was not covered by tests


app = FastAgency(wf=wf, ui=MesopUI())

Check warning on line 136 in docs/docs_src/user_guide/custom_user_interactions/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/custom_user_interactions/main_mesop.py#L136

Added line #L136 was not covered by tests
60 changes: 60 additions & 0 deletions docs/docs_src/user_guide/external_rest_apis/main_mesop.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import os

from autogen import UserProxyAgent
from autogen.agentchat import ConversableAgent

from fastagency import FastAgency
from fastagency import UI
from fastagency.ui.mesop import MesopUI
from fastagency.runtime.autogen.base import AutoGenWorkflows

from fastagency.api.openapi import OpenAPI


llm_config = {

Check warning on line 14 in docs/docs_src/user_guide/external_rest_apis/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/external_rest_apis/main_mesop.py#L14

Added line #L14 was not covered by tests
"config_list": [
{
"model": "gpt-4o-mini",
"api_key": os.getenv("OPENAI_API_KEY"),
}
],
"temperature": 0.0,
}

WEATHER_OPENAPI_URL = "https://weather.tools.fastagency.ai/openapi.json"

Check warning on line 24 in docs/docs_src/user_guide/external_rest_apis/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/external_rest_apis/main_mesop.py#L24

Added line #L24 was not covered by tests

wf = AutoGenWorkflows()

Check warning on line 26 in docs/docs_src/user_guide/external_rest_apis/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/external_rest_apis/main_mesop.py#L26

Added line #L26 was not covered by tests


@wf.register(name="simple_weather", description="Weather chat")
def weather_workflow(ui: UI, initial_message: str, session_id: str) -> str:

Check warning on line 30 in docs/docs_src/user_guide/external_rest_apis/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/external_rest_apis/main_mesop.py#L29-L30

Added lines #L29 - L30 were not covered by tests

weather_api = OpenAPI.create(openapi_url=WEATHER_OPENAPI_URL)

Check warning on line 32 in docs/docs_src/user_guide/external_rest_apis/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/external_rest_apis/main_mesop.py#L32

Added line #L32 was not covered by tests

user_agent = UserProxyAgent(

Check warning on line 34 in docs/docs_src/user_guide/external_rest_apis/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/external_rest_apis/main_mesop.py#L34

Added line #L34 was not covered by tests
name="User_Agent",
system_message="You are a user agent",
llm_config=llm_config,
human_input_mode="NEVER",
)
weather_agent = ConversableAgent(

Check warning on line 40 in docs/docs_src/user_guide/external_rest_apis/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/external_rest_apis/main_mesop.py#L40

Added line #L40 was not covered by tests
name="Weather_Agent",
system_message="You are a weather agent",
llm_config=llm_config,
human_input_mode="NEVER",
)

weather_api.register_for_llm(weather_agent)
weather_api.register_for_execution(user_agent)

Check warning on line 48 in docs/docs_src/user_guide/external_rest_apis/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/external_rest_apis/main_mesop.py#L47-L48

Added lines #L47 - L48 were not covered by tests

chat_result = user_agent.initiate_chat(

Check warning on line 50 in docs/docs_src/user_guide/external_rest_apis/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/external_rest_apis/main_mesop.py#L50

Added line #L50 was not covered by tests
weather_agent,
message=initial_message,
summary_method="reflection_with_llm",
max_turns=3,
)

return chat_result.summary # type: ignore[no-any-return]

Check warning on line 57 in docs/docs_src/user_guide/external_rest_apis/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/external_rest_apis/main_mesop.py#L57

Added line #L57 was not covered by tests


app = FastAgency(wf=wf, ui=MesopUI())

Check warning on line 60 in docs/docs_src/user_guide/external_rest_apis/main_mesop.py

View check run for this annotation

Codecov / codecov/patch

docs/docs_src/user_guide/external_rest_apis/main_mesop.py#L60

Added line #L60 was not covered by tests
2 changes: 1 addition & 1 deletion fastagency/studio/models/agents/assistant.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class AssistantAgent(AgentBaseModel):
Field(
description="The system message of the agent. This message is used to inform the agent about his role in the conversation"
),
] = "You are a helpful assistant. After you successfully answer all questions and there are no new questions asked after your response (e.g. there is no specific direction or question asked after you give a response), terminate the chat by outputting 'TERMINATE'"
] = "You are a helpful assistant. After you successfully answer all questions and there are no new questions asked after your response (e.g. there is no specific direction or question asked after you give a response), terminate the chat by outputting 'TERMINATE' (IMPORTANT: use all caps)"

@classmethod
async def create_autogen(
Expand Down
14 changes: 14 additions & 0 deletions fastagency/ui/mesop/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,13 +221,27 @@ def conversation_worker(ui: MesopUI, subconversation: MesopUI) -> None:
},
)
)

# io.process_message(
# IOMessage.create(
# sender="tester",
# recipient="workflow",
# type="multiple_choice",
# prompt="Concentrate and choose correct answer. When are you going to write unit tests?",
# choices=["Today", "Tomorrow", "Never", "I already have unit tests"],
# default="Tomorrow",
# single=True,
# )
# )

try:
result = wf.run(
name=name,
session_id="session_id",
ui=subconversation, # type: ignore[arg-type]
initial_message=initial_message,
)

except Exception as ex:
ui.process_message(
IOMessage.create(
Expand Down
16 changes: 12 additions & 4 deletions fastagency/ui/mesop/components/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@


def input_user_feedback(
send_feedback: Callable[[me.ClickEvent], Iterator[None]],
send_feedback: Callable[[me.ClickEvent], Iterator[None]], disabled: bool = False
) -> None:
def _on_feedback_blur(e: me.InputBlurEvent) -> None:
state = me.state(State)
state.conversation.feedback = e.value

Check warning on line 19 in fastagency/ui/mesop/components/inputs.py

View check run for this annotation

Codecov / codecov/patch

fastagency/ui/mesop/components/inputs.py#L17-L19

Added lines #L17 - L19 were not covered by tests

with me.box(
style=me.Style(
border_radius=16,
Expand All @@ -26,16 +30,20 @@
with me.box(style=me.Style(flex_grow=1)):
me.native_textarea(
placeholder="Provide a feedback to the team",
on_blur=_on_blur,
key="feedback",
on_blur=_on_feedback_blur,
disabled=disabled,
style=me.Style(
padding=me.Padding(top=16, left=16),
outline="none",
width="100%",
border=me.Border.all(me.BorderSide(style="none")),
),
)
with me.content_button(type="icon", on_click=send_feedback):
with me.content_button(

Check warning on line 42 in fastagency/ui/mesop/components/inputs.py

View check run for this annotation

Codecov / codecov/patch

fastagency/ui/mesop/components/inputs.py#L42

Added line #L42 was not covered by tests
type="icon",
on_click=send_feedback,
disabled=disabled,
):
me.icon("send")


Expand Down
12 changes: 9 additions & 3 deletions fastagency/ui/mesop/data_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
import mesop as me


@dataclass
class ConversationMessage:
io_message_json: str = ""
level: int = 0
conversation_id: str = ""
feedback: list[str] = field(default_factory=list)

Check warning on line 12 in fastagency/ui/mesop/data_model.py

View check run for this annotation

Codecov / codecov/patch

fastagency/ui/mesop/data_model.py#L8-L12

Added lines #L8 - L12 were not covered by tests


@dataclass
class Conversation:
id: str = ""
Expand All @@ -12,8 +20,7 @@
waiting_for_feedback: bool = False
feedback: str = ""
is_from_the_past: bool = False
# messages: list[ConversationMessage] = field(default_factory=list)
messages: list[str] = field(default_factory=list)
messages: list[ConversationMessage] = field(default_factory=list)

Check warning on line 23 in fastagency/ui/mesop/data_model.py

View check run for this annotation

Codecov / codecov/patch

fastagency/ui/mesop/data_model.py#L23

Added line #L23 was not covered by tests
fastagency: Optional[str] = None


Expand All @@ -24,4 +31,3 @@
conversation: Conversation
past_conversations: list[Conversation] = field(default_factory=list)
hide_past: bool = True
fastagency: Optional[str] = None
Loading