Spaces:
Sleeping
Sleeping
File size: 36,612 Bytes
cfd3735 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 |
{
"cells": [
{
"cell_type": "markdown",
"id": "e9732067-71c7-46f7-ad09-381b3bf21a27",
"metadata": {},
"source": [
"# Generative Agents in LangChain\n",
"\n",
"This notebook implements a generative agent based on the paper [Generative Agents: Interactive Simulacra of Human Behavior](https://arxiv.org/abs/2304.03442) by Park, et. al.\n",
"\n",
"In it, we leverage a time-weighted Memory object backed by a LangChain Retriever."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "53f81c37-db45-4fdc-843c-aa8fd2a9e99d",
"metadata": {},
"outputs": [],
"source": [
"# Use termcolor to make it easy to colorize the outputs.\n",
"!pip install termcolor > /dev/null"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "3128fc21",
"metadata": {},
"outputs": [],
"source": [
"import logging\n",
"logging.basicConfig(level=logging.ERROR)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "8851c370-b395-4b80-a79d-486a38ffc244",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from datetime import datetime, timedelta\n",
"from typing import List\n",
"from termcolor import colored\n",
"\n",
"\n",
"from langchain.chat_models import ChatOpenAI\n",
"from langchain.docstore import InMemoryDocstore\n",
"from langchain.embeddings import OpenAIEmbeddings\n",
"from langchain.retrievers import TimeWeightedVectorStoreRetriever\n",
"from langchain.vectorstores import FAISS\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "81824e76",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"USER_NAME = \"Person A\" # The name you want to use when interviewing the agent.\n",
"LLM = ChatOpenAI(max_tokens=1500) # Can be any LLM you want."
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "c3da1649-d88f-4973-b655-7042975cde7e",
"metadata": {},
"source": [
"### Generative Agent Memory Components\n",
"\n",
"This tutorial highlights the memory of generative agents and its impact on their behavior. The memory varies from standard LangChain Chat memory in two aspects:\n",
"\n",
"1. **Memory Formation**\n",
"\n",
" Generative Agents have extended memories, stored in a single stream:\n",
" 1. Observations - from dialogues or interactions with the virtual world, about self or others\n",
" 2. Reflections - resurfaced and summarized core memories\n",
"\n",
"\n",
"2. **Memory Recall**\n",
"\n",
" Memories are retrieved using a weighted sum of salience, recency, and importance.\n",
"\n",
"You can review the definitions of the `GenerativeAgent` and `GenerativeAgentMemory` in the [reference documentation](\"../../reference/modules/experimental\") for the following imports, focusing on `add_memory` and `summarize_related_memories` methods."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "043e5203-6a41-431c-9efa-3e1743d7d25a",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from langchain.experimental.generative_agents import GenerativeAgent, GenerativeAgentMemory"
]
},
{
"cell_type": "markdown",
"id": "361bd49e",
"metadata": {
"jp-MarkdownHeadingCollapsed": true,
"tags": []
},
"source": [
"## Memory Lifecycle\n",
"\n",
"Summarizing the key methods in the above: `add_memory` and `summarize_related_memories`.\n",
"\n",
"When an agent makes an observation, it stores the memory:\n",
" \n",
"1. Language model scores the memory's importance (1 for mundane, 10 for poignant)\n",
"2. Observation and importance are stored within a document by TimeWeightedVectorStoreRetriever, with a `last_accessed_time`.\n",
"\n",
"When an agent responds to an observation:\n",
"\n",
"1. Generates query(s) for retriever, which fetches documents based on salience, recency, and importance.\n",
"2. Summarizes the retrieved information\n",
"3. Updates the `last_accessed_time` for the used documents.\n"
]
},
{
"cell_type": "markdown",
"id": "2fa3ca02",
"metadata": {},
"source": [
"## Create a Generative Character\n",
"\n",
"\n",
"\n",
"Now that we've walked through the definition, we will create two characters named \"Tommie\" and \"Eve\"."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "ee9c1a1d-c311-4f1c-8131-75fccd9025b1",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"import math\n",
"import faiss\n",
"\n",
"def relevance_score_fn(score: float) -> float:\n",
" \"\"\"Return a similarity score on a scale [0, 1].\"\"\"\n",
" # This will differ depending on a few things:\n",
" # - the distance / similarity metric used by the VectorStore\n",
" # - the scale of your embeddings (OpenAI's are unit norm. Many others are not!)\n",
" # This function converts the euclidean norm of normalized embeddings\n",
" # (0 is most similar, sqrt(2) most dissimilar)\n",
" # to a similarity function (0 to 1)\n",
" return 1.0 - score / math.sqrt(2)\n",
"\n",
"def create_new_memory_retriever():\n",
" \"\"\"Create a new vector store retriever unique to the agent.\"\"\"\n",
" # Define your embedding model\n",
" embeddings_model = OpenAIEmbeddings()\n",
" # Initialize the vectorstore as empty\n",
" embedding_size = 1536\n",
" index = faiss.IndexFlatL2(embedding_size)\n",
" vectorstore = FAISS(embeddings_model.embed_query, index, InMemoryDocstore({}), {}, relevance_score_fn=relevance_score_fn)\n",
" return TimeWeightedVectorStoreRetriever(vectorstore=vectorstore, other_score_keys=[\"importance\"], k=15) "
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "7884f9dd-c597-4c27-8c77-1402c71bc2f8",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"tommies_memory = GenerativeAgentMemory(\n",
" llm=LLM,\n",
" memory_retriever=create_new_memory_retriever(),\n",
" verbose=False,\n",
" reflection_threshold=8 # we will give this a relatively low number to show how reflection works\n",
")\n",
"\n",
"tommie = GenerativeAgent(name=\"Tommie\", \n",
" age=25,\n",
" traits=\"anxious, likes design, talkative\", # You can add more persistent traits here \n",
" status=\"looking for a job\", # When connected to a virtual world, we can have the characters update their status\n",
" memory_retriever=create_new_memory_retriever(),\n",
" llm=LLM,\n",
" memory=tommies_memory\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "c524d529",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Name: Tommie (age: 25)\n",
"Innate traits: anxious, likes design, talkative\n",
"No statements were provided about Tommie's core characteristics.\n"
]
}
],
"source": [
"# The current \"Summary\" of a character can't be made because the agent hasn't made\n",
"# any observations yet.\n",
"print(tommie.get_summary())"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "4be60979-d56e-4abf-a636-b34ffa8b7fba",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"# We can add memories directly to the memory object\n",
"tommie_observations = [\n",
" \"Tommie remembers his dog, Bruno, from when he was a kid\",\n",
" \"Tommie feels tired from driving so far\",\n",
" \"Tommie sees the new home\",\n",
" \"The new neighbors have a cat\",\n",
" \"The road is noisy at night\",\n",
" \"Tommie is hungry\",\n",
" \"Tommie tries to get some rest.\",\n",
"]\n",
"for observation in tommie_observations:\n",
" tommie.memory.add_memory(observation)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "6992b48b-697f-4973-9560-142ef85357d7",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Name: Tommie (age: 25)\n",
"Innate traits: anxious, likes design, talkative\n",
"Tommie is a tired and hungry person who is moving into a new home. He remembers his childhood dog and is aware of the new neighbors' cat. He is trying to get some rest despite the noisy road.\n"
]
}
],
"source": [
"# Now that Tommie has 'memories', their self-summary is more descriptive, though still rudimentary.\n",
"# We will see how this summary updates after more observations to create a more rich description.\n",
"print(tommie.get_summary(force_refresh=True))"
]
},
{
"cell_type": "markdown",
"id": "40d39a32-838c-4a03-8b27-a52c76c402e7",
"metadata": {
"tags": []
},
"source": [
"## Pre-Interview with Character\n",
"\n",
"Before sending our character on their way, let's ask them a few questions."
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "eaf125d8-f54c-4c5f-b6af-32789b1f7d3a",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"def interview_agent(agent: GenerativeAgent, message: str) -> str:\n",
" \"\"\"Help the notebook user interact with the agent.\"\"\"\n",
" new_message = f\"{USER_NAME} says {message}\"\n",
" return agent.generate_dialogue_response(new_message)[1]\n"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "54024d41-6e83-4914-91e5-73140e2dd9c8",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"'Tommie said \"I really enjoy design and have been working on some projects in my free time. I\\'m also quite talkative and enjoy meeting new people. What about you?\"'"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"interview_agent(tommie, \"What do you like to do?\")"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "71e2e8cc-921e-4816-82f1-66962b2c1055",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"'Tommie said \"Well, today I\\'m mostly focused on getting settled into my new home. But once that\\'s taken care of, I\\'m looking forward to exploring the neighborhood and finding some new design inspiration. What about you?\"'"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"interview_agent(tommie, \"What are you looking forward to doing today?\")"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "a2521ffc-7050-4ac3-9a18-4cccfc798c31",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"'Tommie said \"Honestly, I\\'m a bit anxious about finding a job in this new area. But I\\'m trying to focus on settling in first and then I\\'ll start my job search. How about you?\"'"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"interview_agent(tommie, \"What are you most worried about today?\")"
]
},
{
"cell_type": "markdown",
"id": "e509c468-f7cd-4d72-9f3a-f4aba28b1eea",
"metadata": {},
"source": [
"## Step through the day's observations."
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "154dee3d-bfe0-4828-b963-ed7e885799b3",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"# Let's have Tommie start going through a day in the life.\n",
"observations = [\n",
" \"Tommie wakes up to the sound of a noisy construction site outside his window.\",\n",
" \"Tommie gets out of bed and heads to the kitchen to make himself some coffee.\",\n",
" \"Tommie realizes he forgot to buy coffee filters and starts rummaging through his moving boxes to find some.\",\n",
" \"Tommie finally finds the filters and makes himself a cup of coffee.\",\n",
" \"The coffee tastes bitter, and Tommie regrets not buying a better brand.\",\n",
" \"Tommie checks his email and sees that he has no job offers yet.\",\n",
" \"Tommie spends some time updating his resume and cover letter.\",\n",
" \"Tommie heads out to explore the city and look for job openings.\",\n",
" \"Tommie sees a sign for a job fair and decides to attend.\",\n",
" \"The line to get in is long, and Tommie has to wait for an hour.\",\n",
" \"Tommie meets several potential employers at the job fair but doesn't receive any offers.\",\n",
" \"Tommie leaves the job fair feeling disappointed.\",\n",
" \"Tommie stops by a local diner to grab some lunch.\",\n",
" \"The service is slow, and Tommie has to wait for 30 minutes to get his food.\",\n",
" \"Tommie overhears a conversation at the next table about a job opening.\",\n",
" \"Tommie asks the diners about the job opening and gets some information about the company.\",\n",
" \"Tommie decides to apply for the job and sends his resume and cover letter.\",\n",
" \"Tommie continues his search for job openings and drops off his resume at several local businesses.\",\n",
" \"Tommie takes a break from his job search to go for a walk in a nearby park.\",\n",
" \"A dog approaches and licks Tommie's feet, and he pets it for a few minutes.\",\n",
" \"Tommie sees a group of people playing frisbee and decides to join in.\",\n",
" \"Tommie has fun playing frisbee but gets hit in the face with the frisbee and hurts his nose.\",\n",
" \"Tommie goes back to his apartment to rest for a bit.\",\n",
" \"A raccoon tore open the trash bag outside his apartment, and the garbage is all over the floor.\",\n",
" \"Tommie starts to feel frustrated with his job search.\",\n",
" \"Tommie calls his best friend to vent about his struggles.\",\n",
" \"Tommie's friend offers some words of encouragement and tells him to keep trying.\",\n",
" \"Tommie feels slightly better after talking to his friend.\",\n",
"]\n"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "238be49c-edb3-4e26-a2b6-98777ba8de86",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[32mTommie wakes up to the sound of a noisy construction site outside his window.\u001b[0m Tommie groans and covers his head with a pillow to try and block out the noise.\n",
"\u001b[32mTommie gets out of bed and heads to the kitchen to make himself some coffee.\u001b[0m Tommie stretches his arms and yawns before making his way to the kitchen.\n",
"\u001b[32mTommie realizes he forgot to buy coffee filters and starts rummaging through his moving boxes to find some.\u001b[0m Tommie sighs in frustration but continues to search through the boxes.\n",
"\u001b[32mTommie finally finds the filters and makes himself a cup of coffee.\u001b[0m Tommie takes a sip of the coffee and smiles, feeling a bit more awake and energized.\n",
"\u001b[32mThe coffee tastes bitter, and Tommie regrets not buying a better brand.\u001b[0m Tommie grimaces and sets down the coffee, disappointed in the taste.\n",
"\u001b[32mTommie checks his email and sees that he has no job offers yet.\u001b[0m Tommie Tommie's shoulders slump and he sighs, feeling discouraged.\n",
"\u001b[32mTommie spends some time updating his resume and cover letter.\u001b[0m Tommie nods to himself, feeling productive and hopeful.\n",
"\u001b[32mTommie heads out to explore the city and look for job openings.\u001b[0m Tommie said \"Do you have any recommendations for good places to look for job openings in the area?\"\n",
"\u001b[32mTommie sees a sign for a job fair and decides to attend.\u001b[0m Tommie said \"That job fair could be a great opportunity for me to network and find some job leads. Thanks for letting me know.\"\n",
"\u001b[32mThe line to get in is long, and Tommie has to wait for an hour.\u001b[0m Tommie sighs and looks around, feeling impatient and frustrated.\n",
"\u001b[32mTommie meets several potential employers at the job fair but doesn't receive any offers.\u001b[0m Tommie Tommie's shoulders slump and he sighs, feeling discouraged.\n",
"\u001b[32mTommie leaves the job fair feeling disappointed.\u001b[0m Tommie Tommie's shoulders slump and he sighs, feeling discouraged.\n",
"\u001b[32mTommie stops by a local diner to grab some lunch.\u001b[0m Tommie said \"Can I get a burger and fries to go, please?\"\n",
"\u001b[32mThe service is slow, and Tommie has to wait for 30 minutes to get his food.\u001b[0m Tommie sighs and looks at his phone, feeling impatient.\n",
"\u001b[32mTommie overhears a conversation at the next table about a job opening.\u001b[0m Tommie said \"Excuse me, I couldn't help but overhear your conversation about the job opening. Do you have any more information about it?\"\n",
"\u001b[32mTommie asks the diners about the job opening and gets some information about the company.\u001b[0m Tommie said \"Thank you for the information, I will definitely look into that company.\"\n",
"\u001b[32mTommie decides to apply for the job and sends his resume and cover letter.\u001b[0m Tommie nods to himself, feeling hopeful and motivated.\n",
"\u001b[32mTommie continues his search for job openings and drops off his resume at several local businesses.\u001b[0m Tommie nods to himself, feeling proactive and hopeful.\n",
"\u001b[32mTommie takes a break from his job search to go for a walk in a nearby park.\u001b[0m Tommie takes a deep breath of fresh air and feels a sense of calm.\n",
"\u001b[32mA dog approaches and licks Tommie's feet, and he pets it for a few minutes.\u001b[0m Tommie smiles and enjoys the moment of affection from the dog.\n",
"****************************************\n",
"\u001b[34mAfter 20 observations, Tommie's summary is:\n",
"Name: Tommie (age: 25)\n",
"Innate traits: anxious, likes design, talkative\n",
"Tommie is hopeful and proactive in his job search, but easily becomes discouraged when faced with setbacks. He enjoys spending time outdoors and interacting with animals. Tommie is also productive and enjoys updating his resume and cover letter. He is talkative, enjoys meeting new people, and has an interest in design. Tommie is also a coffee drinker and seeks advice from others on finding job openings.\u001b[0m\n",
"****************************************\n",
"\u001b[32mTommie sees a group of people playing frisbee and decides to join in.\u001b[0m Do nothing.\n",
"\u001b[32mTommie has fun playing frisbee but gets hit in the face with the frisbee and hurts his nose.\u001b[0m Tommie winces and touches his nose, feeling a bit of pain.\n",
"\u001b[32mTommie goes back to his apartment to rest for a bit.\u001b[0m Tommie takes a deep breath and sinks into his couch, feeling grateful for a moment of relaxation.\n",
"\u001b[32mA raccoon tore open the trash bag outside his apartment, and the garbage is all over the floor.\u001b[0m Tommie sighs and grabs a broom and dustpan to clean up the mess.\n",
"\u001b[32mTommie starts to feel frustrated with his job search.\u001b[0m Tommie sighs and feels discouraged.\n",
"\u001b[32mTommie calls his best friend to vent about his struggles.\u001b[0m Tommie said \"Hey, can I vent to you for a bit about my job search? I'm feeling pretty discouraged.\"\n",
"\u001b[32mTommie's friend offers some words of encouragement and tells him to keep trying.\u001b[0m Tommie said \"Thank you for the encouragement, it means a lot to me.\"\n",
"\u001b[32mTommie feels slightly better after talking to his friend.\u001b[0m Tommie nods to himself, feeling grateful for the support from his friend.\n"
]
}
],
"source": [
"# Let's send Tommie on their way. We'll check in on their summary every few observations to watch it evolve\n",
"for i, observation in enumerate(observations):\n",
" _, reaction = tommie.generate_reaction(observation)\n",
" print(colored(observation, \"green\"), reaction)\n",
" if ((i+1) % 20) == 0:\n",
" print('*'*40)\n",
" print(colored(f\"After {i+1} observations, Tommie's summary is:\\n{tommie.get_summary(force_refresh=True)}\", \"blue\"))\n",
" print('*'*40)"
]
},
{
"cell_type": "markdown",
"id": "dd62a275-7290-43ca-aa0f-504f3a706d09",
"metadata": {},
"source": [
"## Interview after the day"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "6336ab5d-3074-4831-951f-c9e2cba5dfb5",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"'Tommie said \"Well, it\\'s been a bit of a mixed day. I\\'ve had some setbacks in my job search, but I also had some fun playing frisbee and spending time outdoors. How about you?\"'"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"interview_agent(tommie, \"Tell me about how your day has been going\")"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "809ac906-69b7-4326-99ec-af638d32bb20",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"'Tommie said \"I really enjoy coffee, it helps me feel more awake and energized. But sometimes I regret not buying a better brand and finding the taste bitter. How about you?\"'"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"interview_agent(tommie, \"How do you feel about coffee?\")"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "f733a431-19ea-421a-9101-ae2593a8c626",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"'Tommie said \"I actually didn\\'t have a childhood dog, but I\\'ve always loved animals. Do you have any pets?\"'"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"interview_agent(tommie, \"Tell me about your childhood dog!\")"
]
},
{
"cell_type": "markdown",
"id": "c9261428-778a-4c0b-b725-bc9e91b71391",
"metadata": {},
"source": [
"## Adding Multiple Characters\n",
"\n",
"Let's add a second character to have a conversation with Tommie. Feel free to configure different traits."
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "ec8bbe18-a021-419c-bf1f-23d34732cd99",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"eves_memory = GenerativeAgentMemory(\n",
" llm=LLM,\n",
" memory_retriever=create_new_memory_retriever(),\n",
" verbose=False,\n",
" reflection_threshold=5\n",
")\n",
"\n",
"\n",
"eve = GenerativeAgent(name=\"Eve\", \n",
" age=34, \n",
" traits=\"curious, helpful\", # You can add more persistent traits here \n",
" status=\"N/A\", # When connected to a virtual world, we can have the characters update their status\n",
" llm=LLM,\n",
" daily_summaries = [\n",
" (\"Eve started her new job as a career counselor last week and received her first assignment, a client named Tommie.\")\n",
" ],\n",
" memory=eves_memory\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "1e2745f5-e0da-4abd-98b4-830802ce6698",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"yesterday = (datetime.now() - timedelta(days=1)).strftime(\"%A %B %d\")\n",
"eve_observations = [\n",
" \"Eve overhears her colleague say something about a new client being hard to work with\",\n",
" \"Eve wakes up and hear's the alarm\",\n",
" \"Eve eats a boal of porridge\",\n",
" \"Eve helps a coworker on a task\",\n",
" \"Eve plays tennis with her friend Xu before going to work\",\n",
" \"Eve overhears her colleague say something about Tommie being hard to work with\",\n",
"]\n",
"for observation in eve_observations:\n",
" eve.memory.add_memory(observation)"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "de4726e3-4bb1-47da-8fd9-f317a036fe0f",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Name: Eve (age: 34)\n",
"Innate traits: curious, helpful\n",
"Eve is a helpful and active person who enjoys playing tennis, maintaining a healthy diet, and staying aware of her surroundings. She is a responsible employee who is attentive to her coworkers' comments and willing to assist them with tasks.\n"
]
}
],
"source": [
"print(eve.get_summary())"
]
},
{
"cell_type": "markdown",
"id": "837524e9-7f7e-4e9f-b610-f454062f5915",
"metadata": {},
"source": [
"## Pre-conversation interviews\n",
"\n",
"\n",
"Let's \"Interview\" Eve before she speaks with Tommie."
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "6cda916d-800c-47bc-a7f9-6a2f19187472",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"'Eve said \"I\\'m feeling pretty good, thanks for asking! How about you?\"'"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"interview_agent(eve, \"How are you feeling about today?\")"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "448ae644-0a66-4eb2-a03a-319f36948b37",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"'Eve said \"I don\\'t know much about Tommie, why do you ask?\"'"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"interview_agent(eve, \"What do you know about Tommie?\")"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "493fc5b8-8730-4ef8-9820-0f1769ce1691",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"'Eve said \"That\\'s interesting. I don\\'t know much about Tommie, but if I had the chance, I would ask him about his previous work experience and what kind of job he\\'s looking for. What about you, what would you ask him?\"'"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"interview_agent(eve, \"Tommie is looking to find a job. What are are some things you'd like to ask him?\")"
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "4b46452a-6c54-4db2-9d87-18597f70fec8",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"'Eve said \"Sure, I can definitely ask him a lot of questions to keep the conversation going. Thanks for the heads up about his anxiety.\"'"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"interview_agent(eve, \"You'll have to ask him. He may be a bit anxious, so I'd appreciate it if you keep the conversation going and ask as many questions as possible.\")"
]
},
{
"cell_type": "markdown",
"id": "dd780655-1d73-4fcb-a78d-79fd46a20636",
"metadata": {},
"source": [
"## Dialogue between Generative Agents\n",
"\n",
"Generative agents are much more complex when they interact with a virtual environment or with each other. Below, we run a simple conversation between Tommie and Eve."
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "042ea271-4bf1-4247-9082-239a6fea43b8",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"def run_conversation(agents: List[GenerativeAgent], initial_observation: str) -> None:\n",
" \"\"\"Runs a conversation between agents.\"\"\"\n",
" _, observation = agents[1].generate_reaction(initial_observation)\n",
" print(observation)\n",
" turns = 0\n",
" while True:\n",
" break_dialogue = False\n",
" for agent in agents:\n",
" stay_in_dialogue, observation = agent.generate_dialogue_response(observation)\n",
" print(observation)\n",
" # observation = f\"{agent.name} said {reaction}\"\n",
" if not stay_in_dialogue:\n",
" break_dialogue = True \n",
" if break_dialogue:\n",
" break\n",
" turns += 1\n"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "d5462b14-218e-4d85-b035-df57ea8e0f80",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Eve said \"Of course, Tommie. I'd be happy to share about my experience. What specific questions do you have?\"\n",
"Tommie said \"Thank you, Eve. I'm curious about what strategies you used in your own job search. Did you have any specific tactics that helped you stand out to employers?\"\n",
"Eve said \"Sure, Tommie. I found that networking and reaching out to professionals in my field was really helpful. I also made sure to tailor my resume and cover letter to each job I applied to. Do you have any specific questions about those strategies?\"\n",
"Tommie said \"Thank you, Eve. That's really helpful advice. Did you have any specific ways of networking that worked well for you?\"\n",
"Eve said \"Sure, Tommie. I found that attending industry events and connecting with professionals on LinkedIn were both great ways to network. Do you have any specific questions about those tactics?\"\n",
"Tommie said \"That's really helpful, thank you for sharing. Did you find that you were able to make meaningful connections through LinkedIn?\"\n",
"Eve said \"Yes, definitely. I was able to connect with several professionals in my field and even landed a job through a LinkedIn connection. Have you had any luck with networking on LinkedIn?\"\n",
"Tommie said \"That's really impressive! I haven't had much luck yet, but I'll definitely keep trying. Thank you for the advice, Eve.\"\n",
"Eve said \"Glad I could help, Tommie. Is there anything else you want to know?\"\n",
"Tommie said \"Thanks again, Eve. I really appreciate your advice and I'll definitely put it into practice. Have a great day!\"\n",
"Eve said \"You're welcome, Tommie! Don't hesitate to reach out if you have any more questions. Have a great day too!\"\n"
]
}
],
"source": [
"agents = [tommie, eve]\n",
"run_conversation(agents, \"Tommie said: Hi, Eve. Thanks for agreeing to meet with me today. I have a bunch of questions and am not sure where to start. Maybe you could first share about your experience?\")"
]
},
{
"cell_type": "markdown",
"id": "1b28fe80-03dc-4399-961d-6e9ee1980216",
"metadata": {
"tags": []
},
"source": [
"## Let's interview our agents after their conversation\n",
"\n",
"Since the generative agents retain their memories from the day, we can ask them about their plans, conversations, and other memoreis."
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "c4d252f3-fcc1-474c-846e-a7605a6b4ce7",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Name: Tommie (age: 25)\n",
"Innate traits: anxious, likes design, talkative\n",
"Tommie is a hopeful and proactive individual who is searching for a job. He becomes discouraged when he doesn't receive any offers or positive responses, but he tries to stay productive and calm by updating his resume, going for walks, and talking to friends for support. He is also grateful for any encouragement he receives and is motivated to continue his job search. Additionally, he has a fond memory of his childhood pet and enjoys taking breaks to relax.\n"
]
}
],
"source": [
"# We can see a current \"Summary\" of a character based on their own perception of self\n",
"# has changed\n",
"print(tommie.get_summary(force_refresh=True))"
]
},
{
"cell_type": "code",
"execution_count": 30,
"id": "c04db9a4",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Name: Eve (age: 34)\n",
"Innate traits: curious, helpful\n",
"Eve is a helpful and friendly coworker who enjoys playing tennis and eating breakfast. She is attentive and observant, often overhearing conversations around her. She is also proactive and willing to offer advice and assistance to colleagues, particularly in job searching and networking. She is considerate of others' feelings and strives to keep conversations going to make others feel comfortable.\n"
]
}
],
"source": [
"print(eve.get_summary(force_refresh=True))"
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "71762558-8fb6-44d7-8483-f5b47fb2a862",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"'Tommie said \"It was really helpful actually! Eve gave me some great advice on job search strategies and networking. Have you ever tried networking on LinkedIn?\"'"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"interview_agent(tommie, \"How was your conversation with Eve?\")"
]
},
{
"cell_type": "code",
"execution_count": 32,
"id": "085af3d8-ac21-41ea-8f8b-055c56976a67",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"'Eve said \"It was great, thanks for asking! Tommie had some really insightful questions about job searching and networking, and I was happy to offer my advice. How about you, have you had a chance to speak with Tommie recently?\"'"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"interview_agent(eve, \"How was your conversation with Tommie?\")"
]
},
{
"cell_type": "code",
"execution_count": 33,
"id": "5b439f3c-7849-4432-a697-2bcc85b89dae",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"'Eve said \"Well, I think I covered most of the topics Tommie was interested in, but if I had to add one thing, it would be to make sure to follow up with any connections you make during your job search. It\\'s important to maintain those relationships and keep them updated on your progress. Did you have any other questions, Person A?\"'"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"interview_agent(eve, \"What do you wish you would have said to Tommie?\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a17ff5bc-5ad9-4184-8f80-33643e06c589",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
|