equilink-site/code_diagrams/tutorial_diagrams/3_agent_character_sheet.codediagram
2025-02-12 17:38:06 +05:30

1 line
25 KiB
Plaintext

{"id":-1,"name":"Onboarding diagram","userId":-1,"createdAt":"","updatedAt":"","content":{"items":[{"uid":"lW0CrByFpI","position":{"x":-680,"y":800},"sizes":{"width":399.75,"height":223.921875},"autoheight":true,"blockContent":{"content":[{"type":"filePathNode","attrs":{"pathToFile":"","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"main.py"}]},{"type":"codeBlock","attrs":{"language":"python","wrapCode":true},"content":[{"type":"text","text":"# Instantiate your AI model\r\nai_model = GeminiModel()\r\n\n# call step 1\r\nnext_step.step_1(ai_model, debug=False)"}]}]},"nodeType":"block"},{"uid":"RuCwNpe8rs","position":{"x":-680,"y":630},"sizes":{"width":399.75,"height":104.953125},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"We setup our AI Model, and create our Agent Character Sheet that will help the AI make the Twitter posts."}]}]},"color":{"bgColor":"#2b313a","bgName":"black"},"nodeType":"block"},{"uid":"24FHjKbcb4","position":{"x":-100,"y":820},"sizes":{"width":399.75,"height":171.4375},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"filePathNode","attrs":{"pathToFile":"","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"step_1.py"}]},{"type":"codeBlock","attrs":{"language":"python","wrapCode":true},"content":[{"type":"text","text":"def step_1(ai_model, debug=False):\r\n"}]}]},"nodeType":"block"},{"uid":"aPeP7UA4jx","position":{"x":-100,"y":620},"sizes":{"width":399.75,"height":153.9375},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"We have a debug feature that can be turned on and off to help people track down what is going wrong."}]},{"type":"paragraph","content":[{"type":"text","text":"This could also be a separate tests file that is run rather than cluttering up the code here."}]}]},"nodeType":"block"},{"uid":"errABHj0Ma","position":{"x":-130,"y":1260},"sizes":{"width":479.75,"height":381.390625},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"filePathNode","attrs":{"pathToFile":"","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"step_1.py"}]},{"type":"codeBlock","attrs":{"language":"python","wrapCode":true},"content":[{"type":"text","text":"# prompt 1 Character Creation:\r\n# step 1.1: Generate a new agent name, topic, personality, and communication style with the prompt_1 template\r\nprompt_1_vars = {\r\n # \"agent_name\": \"\",\r\n # \"personality\": \"\",\r\n # \"communication_style\": \"\",\r\n # \"topic\": \"\",\n \"concept\": \"alien drone pilot who is a sarcastic asshole visiting earth to report back his findings to his home planet\",\n \"agent_yaml\": yaml.dump(agent)\r\n}\r\n"}]}]},"nodeType":"block"},{"uid":"cgbqTXNQi1","position":{"x":-110,"y":1720},"sizes":{"width":439.78125,"height":146.9375},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"The following is the prompt that has been changed countless times to ensure the AI is returning a yaml file consistently that is valid, as well as the contents of the yaml file that is our secret sauce to the Agent and what it will use to make posts."}]}]},"nodeType":"block"},{"uid":"flbOA-v9zK","position":{"x":-1070,"y":1250},"sizes":{"width":399.765625,"height":416.390625},"autoheight":true,"blockContent":{"content":[{"type":"filePathNode","attrs":{"pathToFile":"","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"templates\\agent_template.yaml"}]},{"type":"codeBlock","attrs":{"language":"yaml","wrapCode":true},"content":[{"type":"text","text":"name:\r\npersonality:\r\ncommunication_style:\r\nbackstory:\r\nuniverse:\r\ntopic_expertise:\r\nhashtags: []\r\nemojis: []\r\nmodel_type: \"gemini\"\r\nmodel_name: \"gemini-exp-1206\"\r\nmemory_store: \"gemini_chroma\"\r\nconnectors:\r\n twitter: true\r\n telegram: false\r\n discord: false\r\n"}]}]},"nodeType":"block"},{"uid":"bk2x5x3hCZ","position":{"x":-90,"y":1060},"sizes":{"width":399.765625,"height":153.9375},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"We can provide any number of details for our agent we want made. "}]},{"type":"paragraph","content":[{"type":"text","text":"It is best to provide a concept, otherwise its just a random concept the AI decides."}]}]},"color":{"bgColor":"#2b313a","bgName":"black"},"nodeType":"block"},{"uid":"GTc84OB9HI","position":{"x":-820,"y":2320},"sizes":{"width":399.765625,"height":223.921875},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"This is the prompt that will generate the Character Sheet for our Agent in a yaml format. "}]},{"type":"paragraph","content":[{"type":"text","text":"Not the placeholders using double {{ Variable_Name }}"}]},{"type":"paragraph","content":[{"type":"text","text":"As is how we can swap out values in our yaml file for anything we want without having to retype a custom prompt for every character, while still allowing the prompt to be flexible and not generic."}]}]},"nodeType":"block"},{"uid":"LkysyEPIGx","position":{"x":-600,"y":1400},"sizes":{"width":399.78125,"height":104.953125},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"This is the ai template we want the ai to fill out and return to us."}]}]},"color":{"bgColor":"#2b313a","bgName":"black"},"nodeType":"block"},{"uid":"40nWX7qZ7r","position":{"x":-90,"y":1950},"sizes":{"width":399.78125,"height":293.90625},"autoheight":true,"blockContent":{"content":[{"type":"filePathNode","attrs":{"pathToFile":"","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"step_1.py"}]},{"type":"codeBlock","attrs":{"language":"python","wrapCode":true},"content":[{"type":"text","text":"# step 1.2: Run the prompt\r\nagent_data = manager.run_prompt(\r\n # prompt_key=\"prompt_1 (Character Creation)\",\r\n prompt_key=\"promot_1 (Character Sheet Creation)\",\r\n template_vars=prompt_1_vars, \r\n ai_model=ai_model,\r\n debug=debug\r\n)"}]}]},"nodeType":"block"},{"uid":"u17DlfDBf8","position":{"x":-1500,"y":2110},"sizes":{"width":589.9375,"height":1431.203125},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"filePathNode","attrs":{"pathToFile":"","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"prompts\\chain_prompts_v2.yaml"}]},{"type":"codeBlock","attrs":{"language":"yaml","wrapCode":true},"content":[{"type":"text","text":"promot_1 (Character Sheet Creation): |\r\n You are an expert in creative writing, character design, world-building, and marketing. You are tasked with developing a complete character profile for a new agent who will be featured in stories for a Twitter bot. These stories will be broken down into seasons, episodes, and individual tweets (scenes/posts).\r\n\r\n Agent Development Task\r\n Generate a comprehensive YAML file that defines this new agent, including their name, personality, communication style, topic of expertise, backstory, universe, relevant hashtags, and emojis.\r\n Use the following concept if its not empty, otherwise create one.\r\n - concept: {{ concept }}\r\n\r\n Specific Instructions:\r\n 1. Invent a Creative Name:\r\n - If no specific name is provided, create a unique and fitting name for the agent based on the concept of the agent. The name should be suitable for a Twitter handle.\r\n - Agent Name: {{ agent_name }}\r\n\r\n 2. Define the Topic: \r\n - If no specific topic is provided, default to \"Crypto\" or invent a creative topic that lends itself to episodic storytelling.\r\n - Topic: {{ topic }}\r\n\r\n 3. Develop Personality and Style:\r\n - Create a detailed personality for the agent.\r\n - Define a clear communication style for the agent.\r\n - Personality: {{ personality }}\r\n - Communication Style: {{ style }}\r\n\r\n 4. Craft a Backstory:\r\n - Invent a compelling and original backstory for the agent that explains their motivations, skills, and current situation. This backstory should be suitable for unfolding gradually over multiple story arcs.\r\n - Backstory: {{ backstory }}\r\n\r\n 5. Describe the Universe:\r\n - Detail the world(s) or setting where the agent operates. Consider the current state of technology, the social and political landscape, major organizations or factions, and any unique elements relevant to the chosen topic.\r\n - Use a narrative or bullet-point format within the YAML.\r\n - Universe: {{ universe }}\r\n\r\n 6. Generate Marketing Elements:\r\n - Create a list of relevant hashtags that will be used for social media promotion. Include hashtags related to the agent's name, topic, and genre.\r\n - Important: Output the hashtags as a YAML array. Enclose the hashtags in square brackets, separate them with commas, make sure they have double quotes around each hashtag, and put each hashtag on a new line within the brackets. (e.g., `hashtags: [\\\\n- \"#example1\",\\\\n- \"#example2\"\\\\n]` )**\r\n - Create a list of relevant emojis that can be used in tweets to add visual interest and convey meaning.\r\n - Important: Output the emojis as a YAML array. Enclose the emojis in square brackets, separate them with commas, and put each emoji on a new line within the brackets. (e.g., `emojis: [\\\\n- 🐳,\\\\n- 🌊\\\\n]` )**\r\n - Hashtags: {{ hashtags }}\r\n - Emojis: {{ emojis }}\r\n\r\n Output Requirements:\r\n - Only output valid YAML. Do not include any text outside of the YAML structure.\r\n - Output a single, complete YAML file that includes all the fields mentioned above (name, personality, communication_style, topic, backstory, universe, hashtags, emojis).\r\n - Adhere to the specified answer lengths for each field (short for personality and communication style, long for backstory and universe).\r\n\r\n Output exactly as the yaml file:\r\n ```yaml\r\n {{ agent_yaml }}\r\n ```"}]}]},"nodeType":"block"},{"uid":"_FbKHtj4_Z","position":{"x":-770,"y":3470},"sizes":{"width":479.84375,"height":496.875},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"We swap out all the place holders values in our yaml file for the prompt_1_vars we created."}]},{"type":"codeBlock","attrs":{"language":"yaml","wrapCode":true},"content":[{"type":"text","text":"{{ concept }}"}]},{"type":"paragraph","content":[{"type":"text","text":"This is achieved by using the following library."}]},{"type":"codeBlock","attrs":{"language":"python","wrapCode":false},"content":[{"type":"text","text":"from jinja2 import Template"}]},{"type":"paragraph","content":[{"type":"text","text":"In this case"}]},{"type":"codeBlock","attrs":{"language":"python","wrapCode":false},"content":[{"type":"text","text":"# The following yaml variable\n{{ concept }}\n\n# Gets replaced with prompt_1_vars concept variable value\n\"alien drone pilot who is a sarcastic asshole visiting \nearth to report back his findings to his home planet\""}]},{"type":"paragraph"}]},"nodeType":"block"},{"uid":"3hymDJ_oQT","position":{"x":-190,"y":2570},"sizes":{"width":639.9375,"height":783.8125},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"filePathNode","attrs":{"pathToFile":"","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"content_generator.py"}]},{"type":"codeBlock","attrs":{"language":"python","wrapCode":true},"content":[{"type":"text","text":"# -------------------------------------------------------------------\r\n# Generic prompt runner that works with any prompt template\r\n# -------------------------------------------------------------------\r\ndef run_prompt(self, prompt_key, template_vars, ai_model, debug=False):\r\n \"\"\"\r\n Generic prompt runner that works with any prompt template\r\n \r\n Args:\r\n prompt_key: The key for the prompt template (e.g., \"prompt_1\", \"prompt_2\")\r\n template_vars: dict of variables to pass to the template\r\n ai_model: The AI model to use for generating responses\r\n \"\"\"\r\n self.ai_model = ai_model\r\n\n # 1. Load the chain prompts from the YAML file\r\n with open(\"prompts/chain_prompts_v2.yaml\", \"r\", encoding=\"utf-8\") as f:\r\n chain_prompts = yaml.safe_load(f)\r\n\n # 2. Grab the raw prompt template text\r\n prompt_template = chain_prompts[prompt_key]\r\n\n # 3. Use Jinja2 to fill placeholders\n template = Template(prompt_template)\n prompt_text = template.render(**template_vars)\n\n # 4. Call the LLM\n response = ai_model.generate_response(prompt_text)\n\n # # 5. Parse the YAML from the LLM's response\n yaml_response = self.parse_yaml_from_response(response)\n if yaml_response is None:\r\n # Handle parse error or fallback\r\n print(f\"Error: LLM returned invalid YAML for {prompt_key}.\")\r\n return None\r\n\n # return yaml_response\r\n return yaml_response"}]}]},"nodeType":"block"},{"uid":"aKUkNhx4oa","position":{"x":-80,"y":2370},"sizes":{"width":399.828125,"height":83.953125},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"Write your note here..."}]}]},"nodeType":"block"},{"uid":"Ka5_2WO78J","position":{"x":-800,"y":2910},"sizes":{"width":399.828125,"height":125.9375},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"The nice things about this function is that it works for all prompts. There is no need to have a custom function for each prompt."}]}]},"nodeType":"block"},{"uid":"ZHSj7Wyw_j","position":{"x":-70,"y":3450},"sizes":{"width":399.84375,"height":104.953125},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"We next have to process the results of the response we get from the AI."}]}]},"nodeType":"block"},{"uid":"xQMZhS6h3z","position":{"x":-70,"y":3890},"sizes":{"width":399.84375,"height":104.953125},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"First we save the raw response. This is a temp file that gets overridden each time."}]}]},"nodeType":"block"},{"uid":"kkQcsDI9vz","position":{"x":-60,"y":4220},"sizes":{"width":399.84375,"height":244.921875},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"We then remove our placed holder values we told the AI to put around our yaml file."}]},{"type":"codeBlock","attrs":{"language":"yaml","wrapCode":false},"content":[{"type":"text","text":"``` yaml\n```"}]},{"type":"paragraph","content":[{"type":"text","text":"we also want to remove any empty lines at the start and end of the file."}]}]},"nodeType":"block"},{"uid":"5CWrjQmahA","position":{"x":-50,"y":4660},"sizes":{"width":399.84375,"height":125.9375},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"We then return the filepath for this file so that we can merge together our template for our AI agent we made at the start, and the new values we received."}]}]},"nodeType":"block"},{"uid":"PotOsSoAv5","position":{"x":-40,"y":4970},"sizes":{"width":399.84375,"height":542.234375},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"Our Character Sheet for our Agents secret sauce should be made. We can then do one of the following:"}]},{"type":"bulletList","content":[{"type":"listItem","content":[{"type":"paragraph","content":[{"type":"text","text":"Character Sheet"}]},{"type":"bulletList","content":[{"type":"listItem","content":[{"type":"paragraph","content":[{"type":"text","text":"Manually edit the files and tweak what we want."}]}]},{"type":"listItem","content":[{"type":"paragraph","content":[{"type":"text","text":"Copy the results and put them into and online AI edit to refine. Just make sure the results are put into a valid yaml file."}]},{"type":"bulletList","content":[{"type":"listItem","content":[{"type":"paragraph","content":[{"type":"text","text":"ChatGPT"}]}]},{"type":"listItem","content":[{"type":"paragraph","content":[{"type":"text","text":"Google Gemini"}]}]},{"type":"listItem","content":[{"type":"paragraph","content":[{"type":"text","text":"Claude."}]}]},{"type":"listItem","content":[{"type":"paragraph","content":[{"type":"text","text":"Just make "}]}]}]}]},{"type":"listItem","content":[{"type":"paragraph","content":[{"type":"text","text":"Re-run the Agent creation process again. You should be provided with a new agent with its own character sheet. To be safe, I would save your current agent to a safe location just in case the AI does create a character with a similar name. Otherwise it will overwrite the files."}]}]}]}]},{"type":"listItem","content":[{"type":"paragraph","content":[{"type":"text","text":"Posts"}]},{"type":"bulletList","content":[{"type":"listItem","content":[{"type":"paragraph","content":[{"type":"text","text":"Move onto the next steps to generate the posts your agent will make and post to social media."}]}]}]}]}]}]},"nodeType":"block"},{"uid":"JNsqZAtg37","position":{"x":-1400,"y":1790},"sizes":{"width":379.9375,"height":276.421875},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"type":"text","text":"Pro Tip."}]},{"type":"paragraph","content":[{"type":"text","text":"To help with marketing and getting your ai out there. I would be selective on the hashtags it uses and includes."}]},{"type":"paragraph","content":[{"type":"text","text":"More importantly, I would have it sign on or off with a hashtag that is its own name. This can help trace back to your agents account if it goes viral. It does not cost you anything and could help get eyes on your agent / project."}]}]},"nodeType":"block"}],"configs":{"centerX":718.6506797353916,"centerY":-136.41252377462126,"zoomLevel":0.5629629445664683},"arrowData":{"arrowsMap":{"arrow-point-bI0wBh3Ufk-bottom-point-PSPLIYKa9J-top":{"to":"point-PSPLIYKa9J-top","from":"point-bI0wBh3Ufk-bottom","label":"Normal Box","direction":"ft","selectable":true},"arrow-point-bI0wBh3Ufk-bottom-point-ytXK_ayIc1-top":{"to":"point-ytXK_ayIc1-top","from":"point-bI0wBh3Ufk-bottom","label":"Code Box","direction":"ft","selectable":true},"arrow-point-hyyRZE3E8u-right-point-6ZopTaEaDZ-left":{"to":"point-6ZopTaEaDZ-left","from":"point-hyyRZE3E8u-right","label":"call","direction":"ft","selectable":true}},"pointsMap":{"point-PSPLIYKa9J-top":{"x":805.9999797489683,"y":60,"id":"point-PSPLIYKa9J-top","direction":"top"},"point-ytXK_ayIc1-top":{"x":205.99999493724206,"y":60,"id":"point-ytXK_ayIc1-top","direction":"top"},"point-6ZopTaEaDZ-left":{"x":220,"y":605.9999898744841,"id":"point-6ZopTaEaDZ-left","direction":"left"},"point-hyyRZE3E8u-right":{"x":100,"y":606,"id":"point-hyyRZE3E8u-right","direction":"right"},"point-bI0wBh3Ufk-bottom":{"x":515.9999797489683,"y":-40,"id":"point-bI0wBh3Ufk-bottom","direction":"bottom"}},"edgesMap":{"edge-RuCwNpe8rs-RuCwNpe8rs-bottom-lW0CrByFpI-lW0CrByFpI-top":{"uid":"edge-RuCwNpe8rs-RuCwNpe8rs-bottom-lW0CrByFpI-lW0CrByFpI-top","fromNodeId":"RuCwNpe8rs","fromHandleId":"RuCwNpe8rs-bottom","toNodeId":"lW0CrByFpI","toHandleId":"lW0CrByFpI-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-lW0CrByFpI-lW0CrByFpI-right-24FHjKbcb4-24FHjKbcb4-left":{"uid":"edge-lW0CrByFpI-lW0CrByFpI-right-24FHjKbcb4-24FHjKbcb4-left","fromNodeId":"lW0CrByFpI","fromHandleId":"lW0CrByFpI-right","toNodeId":"24FHjKbcb4","toHandleId":"24FHjKbcb4-left","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-aPeP7UA4jx-aPeP7UA4jx-bottom-24FHjKbcb4-24FHjKbcb4-top":{"uid":"edge-aPeP7UA4jx-aPeP7UA4jx-bottom-24FHjKbcb4-24FHjKbcb4-top","fromNodeId":"aPeP7UA4jx","fromHandleId":"aPeP7UA4jx-bottom","toNodeId":"24FHjKbcb4","toHandleId":"24FHjKbcb4-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-24FHjKbcb4-24FHjKbcb4-bottom-bk2x5x3hCZ-bk2x5x3hCZ-top":{"uid":"edge-24FHjKbcb4-24FHjKbcb4-bottom-bk2x5x3hCZ-bk2x5x3hCZ-top","fromNodeId":"24FHjKbcb4","fromHandleId":"24FHjKbcb4-bottom","toNodeId":"bk2x5x3hCZ","toHandleId":"bk2x5x3hCZ-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-bk2x5x3hCZ-bk2x5x3hCZ-bottom-errABHj0Ma-errABHj0Ma-top":{"uid":"edge-bk2x5x3hCZ-bk2x5x3hCZ-bottom-errABHj0Ma-errABHj0Ma-top","fromNodeId":"bk2x5x3hCZ","fromHandleId":"bk2x5x3hCZ-bottom","toNodeId":"errABHj0Ma","toHandleId":"errABHj0Ma-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-flbOA-v9zK-flbOA-v9zK-right-LkysyEPIGx-LkysyEPIGx-left":{"uid":"edge-flbOA-v9zK-flbOA-v9zK-right-LkysyEPIGx-LkysyEPIGx-left","fromNodeId":"flbOA-v9zK","fromHandleId":"flbOA-v9zK-right","toNodeId":"LkysyEPIGx","toHandleId":"LkysyEPIGx-left","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-LkysyEPIGx-LkysyEPIGx-right-errABHj0Ma-errABHj0Ma-left":{"uid":"edge-LkysyEPIGx-LkysyEPIGx-right-errABHj0Ma-errABHj0Ma-left","fromNodeId":"LkysyEPIGx","fromHandleId":"LkysyEPIGx-right","toNodeId":"errABHj0Ma","toHandleId":"errABHj0Ma-left","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-cgbqTXNQi1-cgbqTXNQi1-bottom-40nWX7qZ7r-40nWX7qZ7r-top":{"uid":"edge-cgbqTXNQi1-cgbqTXNQi1-bottom-40nWX7qZ7r-40nWX7qZ7r-top","fromNodeId":"cgbqTXNQi1","fromHandleId":"cgbqTXNQi1-bottom","toNodeId":"40nWX7qZ7r","toHandleId":"40nWX7qZ7r-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-errABHj0Ma-errABHj0Ma-bottom-cgbqTXNQi1-cgbqTXNQi1-top":{"uid":"edge-errABHj0Ma-errABHj0Ma-bottom-cgbqTXNQi1-cgbqTXNQi1-top","fromNodeId":"errABHj0Ma","fromHandleId":"errABHj0Ma-bottom","toNodeId":"cgbqTXNQi1","toHandleId":"cgbqTXNQi1-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-GTc84OB9HI-GTc84OB9HI-right-40nWX7qZ7r-40nWX7qZ7r-left":{"uid":"edge-GTc84OB9HI-GTc84OB9HI-right-40nWX7qZ7r-40nWX7qZ7r-left","fromNodeId":"GTc84OB9HI","fromHandleId":"GTc84OB9HI-right","toNodeId":"40nWX7qZ7r","toHandleId":"40nWX7qZ7r-left","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-u17DlfDBf8-u17DlfDBf8-right-GTc84OB9HI-GTc84OB9HI-left":{"uid":"edge-u17DlfDBf8-u17DlfDBf8-right-GTc84OB9HI-GTc84OB9HI-left","fromNodeId":"u17DlfDBf8","fromHandleId":"u17DlfDBf8-right","toNodeId":"GTc84OB9HI","toHandleId":"GTc84OB9HI-left","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-40nWX7qZ7r-40nWX7qZ7r-bottom-aKUkNhx4oa-aKUkNhx4oa-top":{"uid":"edge-40nWX7qZ7r-40nWX7qZ7r-bottom-aKUkNhx4oa-aKUkNhx4oa-top","fromNodeId":"40nWX7qZ7r","fromHandleId":"40nWX7qZ7r-bottom","toNodeId":"aKUkNhx4oa","toHandleId":"aKUkNhx4oa-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-aKUkNhx4oa-aKUkNhx4oa-bottom-3hymDJ_oQT-3hymDJ_oQT-top":{"uid":"edge-aKUkNhx4oa-aKUkNhx4oa-bottom-3hymDJ_oQT-3hymDJ_oQT-top","fromNodeId":"aKUkNhx4oa","fromHandleId":"aKUkNhx4oa-bottom","toNodeId":"3hymDJ_oQT","toHandleId":"3hymDJ_oQT-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-Ka5_2WO78J-Ka5_2WO78J-right-3hymDJ_oQT-3hymDJ_oQT-left":{"uid":"edge-Ka5_2WO78J-Ka5_2WO78J-right-3hymDJ_oQT-3hymDJ_oQT-left","fromNodeId":"Ka5_2WO78J","fromHandleId":"Ka5_2WO78J-right","toNodeId":"3hymDJ_oQT","toHandleId":"3hymDJ_oQT-left","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-3hymDJ_oQT-3hymDJ_oQT-right-_FbKHtj4_Z-_FbKHtj4_Z-top":{"uid":"edge-3hymDJ_oQT-3hymDJ_oQT-right-_FbKHtj4_Z-_FbKHtj4_Z-top","fromNodeId":"3hymDJ_oQT","fromHandleId":"3hymDJ_oQT-right","toNodeId":"_FbKHtj4_Z","toHandleId":"_FbKHtj4_Z-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-_FbKHtj4_Z-_FbKHtj4_Z-left-u17DlfDBf8-u17DlfDBf8-bottom":{"uid":"edge-_FbKHtj4_Z-_FbKHtj4_Z-left-u17DlfDBf8-u17DlfDBf8-bottom","fromNodeId":"_FbKHtj4_Z","fromHandleId":"_FbKHtj4_Z-left","toNodeId":"u17DlfDBf8","toHandleId":"u17DlfDBf8-bottom","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-3hymDJ_oQT-3hymDJ_oQT-bottom-ZHSj7Wyw_j-ZHSj7Wyw_j-top":{"uid":"edge-3hymDJ_oQT-3hymDJ_oQT-bottom-ZHSj7Wyw_j-ZHSj7Wyw_j-top","fromNodeId":"3hymDJ_oQT","fromHandleId":"3hymDJ_oQT-bottom","toNodeId":"ZHSj7Wyw_j","toHandleId":"ZHSj7Wyw_j-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-40nWX7qZ7r-40nWX7qZ7r-bottom-_FbKHtj4_Z-_FbKHtj4_Z-top":{"uid":"edge-40nWX7qZ7r-40nWX7qZ7r-bottom-_FbKHtj4_Z-_FbKHtj4_Z-top","fromNodeId":"40nWX7qZ7r","fromHandleId":"40nWX7qZ7r-bottom","toNodeId":"_FbKHtj4_Z","toHandleId":"_FbKHtj4_Z-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-JNsqZAtg37-JNsqZAtg37-bottom-u17DlfDBf8-u17DlfDBf8-top":{"uid":"edge-JNsqZAtg37-JNsqZAtg37-bottom-u17DlfDBf8-u17DlfDBf8-top","fromNodeId":"JNsqZAtg37","fromHandleId":"JNsqZAtg37-bottom","toNodeId":"u17DlfDBf8","toHandleId":"u17DlfDBf8-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}}}}}}