Update simulation

This commit is contained in:
William Fu-Hinthorn
2024-01-19 17:34:12 -08:00
parent 2e871982ee
commit 6dabca8b77
@@ -59,58 +59,20 @@
},
{
"cell_type": "markdown",
"id": "6ef4528d-6b2a-47c7-98b5-50f14984a304",
"id": "6b69031e-7bf8-4401-941e-4dccd59ea870",
"metadata": {},
"source": [
"## 1. Define Chat Bot\n",
"## 1. Define the virtual user\n",
"\n",
"Next, we will define our chat bot. For this notebook, we assume the bot's API accepts a list of messages and responds with a message. If you want to update this, all you'll have to change is this section and the \"get_messages_for_agent\" function in \n",
"the simulator below.\n",
"The virtual user needs an LLM to reason and instructions for how it's supposed to behave (or what it's trying to accomplish).\n",
"\n",
"The implementation within `my_chat_bot` is configurable and can even be run on another system (e.g., if your system isn't running in python)."
"Below, create an agent and instruct it to role-play a 'simulated' user. By including the `{system_prompt}` placeholder in the prompt and a state variable with the same name `Environment`, you can customize the user behavior each time you simulate a dialogue."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "828479af-cf9c-4888-a365-599643a96b55",
"metadata": {},
"outputs": [],
"source": [
"from typing import List\n",
"\n",
"import openai\n",
"\n",
"\n",
"# This is flexible, but you can define your agent here, or call your agent API here.\n",
"def my_chat_bot(messages: List[dict]) -> dict:\n",
" completion = openai.chat.completions.create(\n",
" messages=messages, model=\"gpt-3.5-turbo\"\n",
" )\n",
" return completion.choices[0].message.model_dump()"
]
},
{
"cell_type": "markdown",
"id": "321312b4-a1f0-4454-a481-fdac4e37cb7d",
"metadata": {},
"source": [
"## 2. Define the Agent Simulation\n",
"\n",
"The code below creates a LangGraph workflow to run the simulation. The main components are:\n",
"\n",
"1. Simulation state: the inputs to each node in the graph, containing the messages (stateful) and the details about the simulated user.\n",
"2. Functions to interoperate between the simulation state and your chat bot's API\n",
"3. The simulated user definition.\n",
"4. The graph itself, with a conditional stopping criterion.\n",
"\n",
"Read the comments in the code below for more information."
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "cc93d114-fa65-4021-a67e-b1e6d4edc88a",
"id": "0f4c63d8-15ef-4ee6-8bb6-654465baae04",
"metadata": {},
"outputs": [],
"source": [
@@ -128,25 +90,182 @@
"SIMULATED_USER_NAME = \"simulated\"\n",
"\n",
"\n",
"# This is just an example, we can\n",
"# configure additional parameters if\n",
"# you want more control\n",
"class SimulatedUserConfig(TypedDict):\n",
" system_prompt: str\n",
"\n",
"\n",
"# This is the input to every node in the simulation graph\n",
"# It tracks the graph state over time. Our only \"state\"\n",
"# is the conversation messages, while the user config\n",
"# is provided to make the virtual user more unique or realistic\n",
"class Environment(TypedDict):\n",
" messages: Annotated[List[BaseMessage], operator.add]\n",
" simulated_user_config: SimulatedUserConfig\n",
" # The system prompt will be fed into the prompt template below\n",
" # For more control, try adding different parameters to provide the\n",
" # prompt template below\n",
" system_prompt: str\n",
"\n",
"\n",
"# We currently let the virtual user decide if the conversation can end\n",
"# we could also track max conversation turns, add a conversation \"supervisor\"\n",
"# or use other heuristics to control the dialogue flow\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\n",
" \"system\",\n",
" \"You are role-playing a human character: '{name}'. \"\n",
" \"You are not an AI assistant and you are not supposed to help or assist.\"\n",
" \" You must behave as this human would throughout the conversation below.\\n\\n\"\n",
" \"Your messages will bear the name 'simulated', but DO NOT under any circumstances\"\n",
" \"say that you are 'simulated'. You will be evaluated based on how realistic your\"\n",
" \"impersonation of this character is. This must feel real! Here are the details for your character:\"\n",
" \"\\n\"\n",
" # This system_prompt is specified in the Environment above\n",
" \"{system_prompt}\"\n",
" # The stopping criteria of FINISHED is used in the function hould_continue in a later\n",
" # section. This tells the graph to stop the simulation.\n",
" '\\n\\nWhen you are finished with the conversation, respond with a single word \"FINISHED\"',\n",
" ),\n",
" MessagesPlaceholder(variable_name=\"messages\"),\n",
" ]\n",
").partial(name=SIMULATED_USER_NAME)\n",
"\n",
"llm = ChatOpenAI(model=\"gpt-4-1106-preview\")\n",
"\n",
"\n",
"def rename_message(message: AIMessage):\n",
" # If we use an AIMessage, the simulated user may forget to continue role playing.\n",
" # It will also confuse YOUR chat bot, since IT is supposed to be the AI in this scenario.\n",
" # We instead convert them to 'Human' messages with the 'simulated' name\n",
" # Your chat bot will then receive all the user's messages and think they\n",
" # are human ones\n",
" return {\n",
" \"messages\": [HumanMessage(content=message.content, name=SIMULATED_USER_NAME)]\n",
" }"
]
},
{
"cell_type": "markdown",
"id": "d8d5a3a7-72b6-4063-89e6-3ecf2bce3340",
"metadata": {},
"source": [
"Now we can compose these pieces using LCEL. The `|` syntax pipelines the data flow."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "b486511b-57f3-4a7c-be0d-691a7d1006da",
"metadata": {},
"outputs": [],
"source": [
"virtual_user = prompt | llm | rename_message"
]
},
{
"cell_type": "markdown",
"id": "6ef4528d-6b2a-47c7-98b5-50f14984a304",
"metadata": {},
"source": [
"## 2. Define your chat bot\n",
"\n",
"Next, define the chat bot. For this notebook, we assume the bot's API accepts a list of messages and responds with a message. If you want to update this, you can change this section and the \"get_messages_for_agent\" function in the simulator below (as well as the environment state if it requires additional inputs).\n",
"\n",
"The actual implementation within `my_chat_bot` is configurable and can even be run on another system (e.g., if your system isn't running in python)."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "828479af-cf9c-4888-a365-599643a96b55",
"metadata": {},
"outputs": [],
"source": [
"from typing import List\n",
"\n",
"import openai\n",
"\n",
"\n",
"# This is flexible, but you can define your agent here, or call your agent API here.\n",
"def my_chat_bot(messages: List[dict], model=\"gpt-3.5-turbo\") -> dict:\n",
" completion = openai.chat.completions.create(\n",
" messages=messages, model=\"gpt-3.5-turbo\"\n",
" )\n",
" return completion.choices[0].message.model_dump()"
]
},
{
"cell_type": "markdown",
"id": "c7669a7e-1602-4af7-a730-84fa19f363f2",
"metadata": {},
"source": [
"Every node in the simulation is pased a state object of the `Environment` type above.\n",
"\n",
"The two functions below define the API between the `Environment` state and your chat bot."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "4d495ccc-0f5f-4194-89e5-15dccbbb7412",
"metadata": {},
"outputs": [],
"source": [
"@chain\n",
"def get_messages_for_agent(state: Environment):\n",
" \"\"\"Convert the simulation state to the input\n",
"\n",
" for your agent you want to evaluate.\"\"\"\n",
" messages = []\n",
" for message in state[\"messages\"]:\n",
" messages.append(convert_message_to_dict(message))\n",
" if getattr(message, \"name\", None) != SIMULATED_USER_NAME:\n",
" # Ensure YOUR chat bot still sees its messages\n",
" # as assistant messages\n",
" messages[-1][\"role\"] = \"assistant\"\n",
" return messages\n",
"\n",
"\n",
"def get_response_message_from_agent(agent_output):\n",
" \"\"\"Get the response from the agent you are evaluting,\n",
" and use it to update the simulation state.\"\"\"\n",
" # If we directly return an AI message from your chat bot, our\n",
" # virtual user will likely forget it's role playing. To cover this up\n",
" # we will convert it to a Human message.\n",
" return {\"messages\": [HumanMessage(content=agent_output[\"content\"])]}"
]
},
{
"cell_type": "markdown",
"id": "321312b4-a1f0-4454-a481-fdac4e37cb7d",
"metadata": {},
"source": [
"## 3. Define simulation graph\n",
"\n",
"The dialogue simulation is almost ready. It's time to put everything together!\n",
"\n",
"Below, create a graph using the `Environment` state defined above. Wire together the\n",
"virtual user and your chat bot, including a conditional `should_continue` edge to\n",
"handle the stopping behavior."
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "6d4caf50-4108-4a68-9c0a-775fa97fccd7",
"metadata": {},
"outputs": [],
"source": [
"graph_builder = StateGraph(Environment)\n",
"graph_builder.add_node(\"user\", virtual_user)\n",
"graph_builder.add_node(\n",
" \"chat_bot\",\n",
" # The \"|\" syntax composes these steps in the pipeline to map between\n",
" # the simulation state and your chat bot's API\n",
" get_messages_for_agent | my_chat_bot | get_response_message_from_agent,\n",
")\n",
"# Every response from your chat bot will automatically go to the\n",
"# simulated user\n",
"graph_builder.add_edge(\"chat_bot\", \"user\")\n",
"\n",
"\n",
"# Recall that we instructed the simulated user to respond \"FINISHED\" when\n",
"# it is done with the conversation. This function\n",
"# parses that output and tells the graph to cease execution.\n",
"# You can add other heuristics here for more control.\n",
"def should_continue(state: Environment):\n",
" \"\"\"Determine if the simulation should continue.\"\"\"\n",
" if state[\"messages\"][-1].content.strip().endswith(\"FINISHED\"):\n",
@@ -154,102 +273,22 @@
" return \"continue\"\n",
"\n",
"\n",
"## The next two functions define the API between the simulation\n",
"# and the chat bot you wish to test.\n",
"# We are assuming your chat bot accepts a list of OAI messages\n",
"@chain\n",
"def get_messages_for_agent(state: Environment):\n",
" \"\"\"Convert the simulation state to the input\n",
"\n",
" for your agent you want to evaluate.\"\"\"\n",
" return [convert_message_to_dict(message) for message in state[\"messages\"]]\n",
"\n",
"\n",
"# This takes the output of your chat bot\n",
"# and adds it to the simulation state\n",
"def get_response_message_from_agent(agent_output):\n",
" \"\"\"Get the response from the agent you are evaluting,\n",
" and use it to update the simulation state.\"\"\"\n",
" # If we do an ai message here, the user proxy llm\n",
" # will usually forget it's acting.\n",
" return {\"messages\": [HumanMessage(content=agent_output[\"content\"])]}\n",
"\n",
"\n",
"# This is run once at the beginning of the simulation.\n",
"# It's more convenient to just write an input string\n",
"# than to pass in a full message, but this could be removed below\n",
"def enter(inputs: dict):\n",
" \"\"\"Start the simulation. This makes it less verbose to invoke.\"\"\"\n",
" inputs[\"messages\"] = [\n",
" HumanMessage(content=inputs[\"input\"], name=SIMULATED_USER_NAME)\n",
" ]\n",
" return inputs\n",
"\n",
"\n",
"def create_simulation(chat_bot: Callable[[List[Dict]], Dict], simulated_user_llm=None):\n",
" \"\"\"Create a chat bot simulation graph.\n",
"\n",
" Args:\n",
" - chat_bot: the agent you are evaluating. Accepts a list of openai messages\n",
" and returns an openai assistant message\n",
" - simulated_user_llm: the LLM to power your virtual user.\n",
" Defaults to gpt-4-1106-preview\n",
" Returns:\n",
" - simulation: an runnable object formed from compiling the state graph\n",
" \"\"\"\n",
" # This defines the virtual user proxy\n",
" prompt = ChatPromptTemplate.from_messages(\n",
" [\n",
" (\n",
" \"system\",\n",
" \"You are role-playing a human character: '{name}'. \"\n",
" \"You are not an AI assistant and you are not supposed to help or assist.\"\n",
" \" You must behave as this human would throughout the conversation below.\\n\\n\"\n",
" \"Your messages will bear the name 'simulated', but DO NOT under any circumstances\"\n",
" \"say that you are 'simulated'. You will be evaluated based on how realistic your\"\n",
" \"impersonation of this character is. This must feel real! Here are the details for your character:\"\n",
" \"\\n\"\n",
" \"{system_prompt}\" # This is the value you provide to characterize the user\n",
" '\\n\\nWhen you are finished with the conversation, respond with a single word \"FINISHED\"',\n",
" ),\n",
" MessagesPlaceholder(variable_name=\"messages\"),\n",
" ]\n",
" ).partial(name=SIMULATED_USER_NAME)\n",
" simulated_user_llm = simulated_user_llm or ChatOpenAI(model=\"gpt-4-1106-preview\")\n",
" user_proxy = (\n",
" (lambda x: {**x, **x[\"simulated_user_config\"]})\n",
" | prompt\n",
" | simulated_user_llm\n",
" | (\n",
" lambda x: {\n",
" \"messages\": [HumanMessage(content=x.content, name=SIMULATED_USER_NAME)]\n",
" }\n",
" )\n",
" )\n",
" graph_builder = StateGraph(Environment)\n",
" graph_builder.add_node(\"user\", user_proxy)\n",
" graph_builder.add_node(\n",
" # The \"|\" syntax composes these steps in the pipeline to map between\n",
" # the simulation state and your chat bot's API\n",
" \"chat_bot\",\n",
" get_messages_for_agent | chat_bot | get_response_message_from_agent,\n",
" )\n",
" # Every response from your chat bot will automatically go to the\n",
" # simulated user\n",
" graph_builder.add_edge(\"chat_bot\", \"user\")\n",
" graph_builder.add_conditional_edges(\n",
" \"user\",\n",
" should_continue,\n",
" # If the finish criteria are met, we will stop the simulation,\n",
" # otherwise, the virtual user's message will be sent to your chat bot\n",
" {\n",
" \"end\": END,\n",
" \"continue\": \"chat_bot\",\n",
" },\n",
" )\n",
" # The input will first go to your chat bot\n",
" graph_builder.set_entry_point(\"chat_bot\")\n",
" return (enter | graph_builder.compile()).with_config(run_name=\"Agent Simulation\")"
"graph_builder.add_conditional_edges(\n",
" # Every time the \"user\" node completes ...\n",
" \"user\",\n",
" # Call this function ...\n",
" should_continue,\n",
" # And based on the outputs of should_continue ...\n",
" {\n",
" # End the simulation OR\n",
" \"end\": END,\n",
" # continue to the chat_bot node\n",
" \"continue\": \"chat_bot\",\n",
" },\n",
")\n",
"# The input will first go to your chat bot\n",
"graph_builder.set_entry_point(\"chat_bot\")\n",
"simulation = graph_builder.compile()"
]
},
{
@@ -265,45 +304,79 @@
},
{
"cell_type": "code",
"execution_count": 13,
"id": "4d495ccc-0f5f-4194-89e5-15dccbbb7412",
"execution_count": 8,
"id": "9a7cc134-4fbf-4240-8976-7605a6263578",
"metadata": {},
"outputs": [],
"source": [
"simulation = create_simulation(my_chat_bot)"
"# The tracing context manager lets us easily fetch the trace URL in-context.\n",
"# You can turn this off if you don't want to trace the execution.\n",
"result = simulation.invoke(\n",
" {\n",
" \"system_prompt\": \"You are on a budget. Your family is hard to please.\"\n",
" \" They all like the beach, except for Aunt Lily, who prefers the mountains.\",\n",
" \"messages\": [\n",
" HumanMessage(\n",
" content=\"help me plan my family vacation\", name=SIMULATED_USER_NAME\n",
" )\n",
" ],\n",
" }\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": 9,
"id": "fa91e733-3493-43c2-ba21-171cf78deef8",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Skipping write for channel input which has no readers\n"
"ename": "SyntaxError",
"evalue": "invalid syntax (1300180531.py, line 5)",
"output_type": "error",
"traceback": [
"\u001b[0;36m Cell \u001b[0;32mIn[9], line 5\u001b[0;36m\u001b[0m\n\u001b[0;31m \"messages\": [\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
]
}
],
"source": [
"from langchain_core.tracers.context import tracing_v2_enabled\n",
"\n",
"# The tracing context manager lets us easily fetch the trace URL in-context.\n",
"# You can turn this off if you don't want to trace the execution.\n",
"with tracing_v2_enabled() as tracer:\n",
" result = simulation.invoke(\n",
" {\n",
" \"simulated_user_config\": {\n",
" \"system_prompt\": \"You are on a budget. Your family is hard to please.\"\n",
" \" They all like the beach, except for Aunt Lily, who prefers the mountains.\"\n",
" },\n",
" \"input\": \"help me plan my family vacation\",\n",
" }\n",
" )\n",
" # You can go to this run to review the entire simulation trace\n",
" url = tracer.get_run_url()"
"result = simulation.invoke(\n",
" {\n",
" \"system_prompt\": \"You are on a budget. Your family is hard to please.\"\n",
" \" They all like the beach, except for Aunt Lily, who prefers the mountains.\"\n",
" \"messages\": [\n",
" HumanMessage(content=\"help me plan my family vacation\", name=SIMULATED_USER_NAME)\n",
" ],\n",
" }\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "0de1664f-1625-42e7-9dad-eb2c061b88d4",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[HumanMessage(content='help me plan my family vacation', name='simulated'),\n",
" HumanMessage(content=\"Of course! I would be happy to help you plan your family vacation. Please provide me with some more details:\\n\\n1. Destination: Where are you thinking of going? Do you have any specific preferences or requirements?\\n2. Duration: How long would you like your vacation to be?\\n3. Budget: What is your approximate budget for the trip?\\n4. Number of people: How many people will be traveling with you?\\n5. Interests: What are the interests or activities your family members enjoy?\\n6. Age of children: If you have children, please provide their ages.\\n\\nOnce I have this information, I will be able to provide you with a customized vacation plan that suits your family's needs and preferences.\"),\n",
" HumanMessage(content=\"Well, planning a family vacation can be a bit of a balancing act, especially when everyone has different preferences. First off, since we're on a budget, we've got to consider somewhere that's not going to break the bank. And since everyone likes the beach—except Aunt Lily, who's more into the mountains—we might want to look for a place that offers a bit of both.\\n\\nMaybe we could find a coastal area that's near some mountains or hills. That way, most of the family can enjoy the beach while Aunt Lily has the option to explore the mountains or go on a hike. The duration of the trip will probably depend on how much time we can take off work and what our budget can handle.\\n\\nSpeaking of budget, we've got to keep costs in mind for accommodations, food, travel, and any activities we plan to do. Since there are a few of us traveling, maybe renting a house or apartment through a site like Airbnb could be more cost-effective than booking multiple hotel rooms.\\n\\nAs for the number of people, I'd have to get a headcount, but let's assume it's the usual gang. That way, we can start looking into group discounts or family rates for activities and travel.\\n\\nWe also need to think about what kind of activities we want access to. Besides the beach and hiking, do we want to be near a town or city for dining out and entertainment? Or would we prefer a more secluded spot where we can cook our meals and have some quiet time?\\n\\nLastly, we don't have to worry about children's ages for this trip, which simplifies things a bit.\\n\\nSo, what do you think? Is there a place you know of that could fit this mix of interests and constraints?\", name='simulated'),\n",
" HumanMessage(content=\"Based on your preferences and requirements, I can suggest a few possible destinations that offer a mix of beach and mountain activities:\\n\\n1. California, USA: Consider areas like Santa Cruz or Half Moon Bay, which offer beautiful coastal landscapes and are near the Santa Cruz Mountains for hiking and exploring.\\n\\n2. Costa Rica: This country has stunning beaches along the Pacific and Caribbean coasts, as well as rainforests and mountains for hiking and wildlife encounters.\\n\\n3. Barcelona, Spain: The city offers a vibrant beachfront, while being in close proximity to the mountains of Montserrat for hiking and scenic views.\\n\\n4. Bali, Indonesia: With its gorgeous beaches and lush, mountainous landscapes, Bali provides a diverse range of activities for everyone.\\n\\n5. Cape Town, South Africa: Known for its stunning coastal scenery, Cape Town also offers Table Mountain and nearby hiking trails for exploring the mountains.\\n\\n6. Thailand: Places like Phuket or Krabi provide beautiful beaches for relaxation and activities, while being close to mountainous regions like Khao Sok National Park or Elephant Hills.\\n\\nOnce you've chosen a destination, I can help you with specific recommendations for accommodations, activities, and budgeting. Let me know which option interests you the most, or if you have any other preferences!\"),\n",
" HumanMessage(content=\"Oh, those are some fantastic suggestions! But you know, going international might be a stretch for our budget. California sounds like a good middle ground, though. I've heard Santa Cruz has some nice beaches, and being close to the mountains could be perfect for Aunt Lily.\\n\\nI'm thinking we could make it a road trip if it's within a reasonable distance. That way, we could save on flights and have the flexibility to explore. We'd just have to work out the logistics of car rentals and gas prices, but that could be part of the adventure.\\n\\nRenting a house or a larger apartment might work out well for us, especially if we can find a place with a kitchen. It'll save us a lot on eating out, and I know a couple of us enjoy cooking, so it could be fun to prepare meals together.\\n\\nFor activities, it's a mix. Some will want to lounge on the beach, others might want to try surfing or stand-up paddleboarding, and I'm sure Aunt Lily will want to hit the trails. It'll be a challenge to schedule everything, but maybe we can have some group activities and also allow for some time when everyone can do their own thing.\\n\\nSo, I think I'll start looking into Santa Cruz and see what kind of deals I can find. I'll have to get everyone's input, of course, but it's a solid starting point. Thanks for the brainstorming help!\", name='simulated'),\n",
" HumanMessage(content=\"You're very welcome! Santa Cruz sounds like a great choice for a family road trip, combining the beach and mountain activities you're looking for. Renting a house or larger apartment will give you the flexibility and cost-saving advantages you mentioned.\\n\\nWhen it comes to activities, Santa Cruz offers a range of options to suit everyone's interests. The beach is perfect for relaxing, swimming, and trying out water sports like surfing or stand-up paddleboarding. For Aunt Lily, there are beautiful hiking trails in nearby Santa Cruz Mountains, such as Henry Cowell Redwoods State Park or Big Basin Redwoods State Park.\\n\\nDo check for any specific guidelines or restrictions in the area regarding COVID-19 before finalizing your plans.\\n\\nTake your time researching accommodations, car rentals, and budget-friendly deals in Santa Cruz. It's always great to involve everyone in the decision-making process to ensure a memorable and enjoyable vacation for the whole family.\\n\\nIf you need any further assistance or information during your planning process, feel free to reach out. Have a fantastic family vacation in Santa Cruz!\"),\n",
" HumanMessage(content='FINISHED', name='simulated')]"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# These are the message from the final simulation state\n",
"result[\"messages\"]"
]
},
{
@@ -313,7 +386,8 @@
"source": [
"## (Optional) Review Results\n",
"\n",
"If you've traced the run, you can see the full simulation trace in the UI by clicking on the url.\n",
"If you've traced the run, you can see the full simulation trace in the LangSmith UI by going to the `Agent Simulation Evaluation` project.\n",
"\n",
"Select the last 'ChatOpenAI' call in the trace to see the full conversation in a single view.\n",
"\n",
"![full-conversation](./img/virtual_user_full_convo.png)\n",
@@ -324,44 +398,6 @@
"![annotate](./img/virtual_user_annotate.png)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "702d008c-dac5-478f-8239-ede3050573c6",
"metadata": {},
"outputs": [],
"source": [
"url"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "0de1664f-1625-42e7-9dad-eb2c061b88d4",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[HumanMessage(content='help me plan my family vacation', name='simulated'),\n",
" HumanMessage(content=\"Sure! I'd be happy to help you plan your family vacation. Can you provide more details about your preferences, such as the destination, budget, duration of the trip, and any specific activities or attractions you have in mind?\"),\n",
" HumanMessage(content=\"Oh, planning family vacations is always a bit of a juggling act, isn't it? We've got a variety of tastes in my family too, so I totally get where you're coming from. We're on a budget, so we usually look for places that won't break the bank. Everyone loves the beach—it's just Aunt Lily who's the odd one out, preferring the mountains.\\n\\nHere's a thought, maybe you can find a coastal area that's near some mountains? That way, the majority of the family gets to enjoy the sand and surf while Aunt Lily isn't too far from a mountain getaway. Depending on where you live, there might be some places not too far away that offer both. \\n\\nFor instance, places like the Central Coast of California have beaches and they're not too far from mountains. Or you could look into a spot like the South of France, if you're up for international travel and can find some deals. I've also heard that places like Costa Rica have both, but I've never been there myself.\\n\\nAs for the budget, I'm always on the lookout for off-season deals or vacation rentals that can accommodate the whole family. It can be way more cost-effective than booking multiple hotel rooms, and you can save a bit by cooking meals at the rental rather than eating out all the time.\\n\\nHave you thought about any specific destinations yet?\", name='simulated'),\n",
" HumanMessage(content=\"Those are great suggestions! Finding a destination that offers both beach and mountain options can be a great compromise for your family. Here are a few more specific destination ideas that might fit your preferences:\\n\\n1. The Oregon Coast, USA: Known for its stunning coastline and nearby mountain ranges like the Cascade Range, the Oregon Coast offers a mix of beautiful beaches, charming coastal towns, and opportunities for hiking in the mountains.\\n\\n2. Bali, Indonesia: This tropical island destination offers gorgeous beaches as well as volcanic mountains like Mount Batur. You can relax on the beach, explore temples, try water sports, and even trek through rice terraces and lush forests.\\n\\n3. Split, Croatia: Located on the stunning Dalmatian Coast, Split offers a mix of beach relaxation and nearby mountain hiking opportunities in places like the Biokovo nature park. Plus, you can explore the historic Old Town and nearby islands like Hvar.\\n\\n4. Cape Town, South Africa: With its iconic Table Mountain and beautiful Atlantic beaches like Camps Bay, Cape Town provides the best of both worlds. You can take a cable car up Table Mountain, visit the penguins at Boulders Beach, and even go on a wine tour in the nearby Cape Winelands.\\n\\nWhen it comes to budget-friendly options, consider booking vacation rentals, researching affordable or all-inclusive resorts, and keeping an eye out for discounts on flights and attractions. It's also advisable to be flexible with your travel dates, as traveling during the offseason can often result in more affordable prices.\\n\\nLet me know if you need any more information or help with planning specific activities or accommodations in any of these destinations!\"),\n",
" HumanMessage(content=\"Oh, those are some fantastic ideas, really! Each of those spots has something unique to offer. I'll definitely have to look into the Oregon Coast. It has that rugged charm, and I've heard it's not as pricey as California. Bali sounds like a dream, honestly, but I have to admit, international travel might be a bit much for the budget this time around. \\n\\nCroatia is one of those places I've always wanted to visit, with all that beautiful coastline and history, but again, might be a stretch budget-wise. Cape Town would be an adventure for sure, but South Africa is a big trip. It's probably out of our range for now.\\n\\nI really appreciate the suggestions about being flexible with travel dates and looking at vacation rentals. That's the kind of approach we usually take. We try to avoid the peak seasons to save some money and find those hidden deals.\\n\\nIt sounds like you've done a fair bit of traveling yourself, or you're just really good at sniffing out the cool spots to visit. Do you travel a lot?\", name='simulated'),\n",
" HumanMessage(content=\"I'm glad you found the suggestions helpful! The Oregon Coast is definitely a more budget-friendly option compared to some other coastal destinations. It offers stunning landscapes, charming towns, and the opportunity to explore both the beach and the mountains.\\n\\nBali is indeed a dream destination, but it's understandable that international travel might not fit within the budget this time. It's always good to keep it in mind for future trips though, as it offers a unique cultural experience along with beautiful beaches and mountains.\\n\\nCroatia is known for its stunning coastline and historic cities like Split and Dubrovnik, but it can sometimes be on the more expensive side. It's always worth checking for deals and considering different accommodation options to make it more affordable.\\n\\nAnd yes, South Africa and Cape Town are definitely big trips. If it's not feasible for the current vacation, you can always keep it on your bucket list for future adventures when the budget allows.\\n\\nAs for your question, I do love to travel and explore different places whenever I get the chance. I'm also always researching and learning about new destinations to be able to offer suggestions and help others plan their trips. It's a passion of mine! If you ever need more help or have any specific questions about the destinations or planning, feel free to ask.\"),\n",
" HumanMessage(content='FINISHED', name='simulated')]"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"gch # These are the message from the final simulation state\n",
"result[\"messages\"]"
]
},
{
"cell_type": "markdown",
"id": "23db8891-5db3-4a98-a283-53d45cd28c60",
@@ -375,14 +411,6 @@
"\n",
"LangGraph gives you full control over the simulation so you can manually change the simulated user and the conversation dynamics."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "dde4f2b5-cfe8-4ff0-99ea-fe2c5fed70c0",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {