diff --git a/README.md b/README.md index a0a165a..87e132b 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,37 @@ You can previous and download more examples [here](examples/README.md). ## Recent Changelog +### Nov 26, 2024 +* Upgrade to Griptape Framework v0.34.3 +* New Nodes: + * `Griptape Driver: Black Forest Labs Image Generation` - Now generate images with the incredible Flux models - `flux-pro-1.1`, `flux-pro`, `flux-dev`, and `flux-pro-1.1-ultra`. + - Requires an API_KEY from Black Forest Labs (https://docs.bfl.ml/) + - Utilizes new Griptape Extension: https://github.com/griptape-ai/griptape-black-forest + + ![Black Forest Labs - Create Image](examples/griptape_black_forest_labs_create_image.png) + + - It also works with the `Griptape Create: Image Variation` node. + + ![Black Forest Labs - Image Variation](examples/griptape_black_forest_labs_create_variation.png) + + * `Griptape Create: Image Inpainting Variation` to the Griptape -> Image menu. Gives the ability to paint a mask and replace that part of the image. + + ![Black Forest Labs - Inpainting](examples/griptape_black_forest_flux_inpainting.png) + + * `Griptape Run: Task` - Combines/Replaces `Griptape Run: Prompt Task`, `Griptape Run: Tool Task`, and `Griptape Run Toolkit Task` into a single node that knows what to do. + * `Griptape Run: Text Extraction` to the Griptape -> Text menu +* Added `keep_alive` parameter to `Ollama Prompt Driver` to give the user the ability to control how long to keep the model running. Setting it to 0 will do the same as an `ollama stop ` command-line execution. Default setting is 240 seconds to match the current default. + +* Moved node: `Griptape Run: Text Summary` to the Griptape -> Text menu +* Updated `Griptape RAG Retrieve: Text Loader Module` to take a file input or text input. +* Fixed ExtractionTool to use a default of `gpt-4o-mini` +* Added some text files for testing text loading +* Added Examples to [Examples Readme](examples/README.md) + * [Render Log Review](examples/render_log_review.png) + * [Flux Pro 1.1 Image Generation](examples/griptape_black_forest_labs_create_image.png) + * [Flux Pro 1.0-Canny Image Variation](examples/griptape_black_forest_labs_create_variation.png) + * [Flux Pro 1.0-Fill Image InPainting](examples/griptape_black_forest_flux_inpainting.png) + ### Nov 9, 2024 * Upgrade to Griptape Framework v0.34.2 * Fixed combine nodes breaking when re-connecting output diff --git a/__init__.py b/__init__.py index 0a7dd0a..0e24998 100644 --- a/__init__.py +++ b/__init__.py @@ -118,6 +118,11 @@ gtUIAzureOpenAiImageGenerationDriver, ) +# - BlackForest Labs +from .nodes.drivers.gtUIBlackForestImageGenerationDriver import ( + gtUIBlackForestImageGenerationDriver, +) + # - Cohere from .nodes.drivers.gtUICohereEmbeddingDriver import gtUICohereEmbeddingDriver from .nodes.drivers.gtUICoherePromptDriver import gtUICoherePromptDriver @@ -236,17 +241,24 @@ # RULES from .nodes.rules.gtUIRule import gtUIRule -# TASKS # - Audio from .nodes.tasks.gtUIAudioTranscriptionTask import gtUIAudioTranscriptionTask +from .nodes.tasks.gtUIExtractionTask import gtUIExtractionTask # - Image from .nodes.tasks.gtUIImageQueryTask import gtUIImageQueryTask +from .nodes.tasks.gtUIInpaintingImageGenerationTask import ( + gtUIInpaintingImageGenerationTask, +) from .nodes.tasks.gtUIParallelImageQueryTask import gtUIParallelImageQueryTask from .nodes.tasks.gtUIPromptImageGenerationTask import gtUIPromptImageGenerationTask from .nodes.tasks.gtUIPromptImageVariationTask import gtUIPromptImageVariationTask from .nodes.tasks.gtUIPromptTask import gtUIPromptTask +# TASKS +# - Agent +from .nodes.tasks.gtUITask import gtUITask + # - Text from .nodes.tasks.gtUITextSummaryTask import gtUITextSummaryTask from .nodes.tasks.gtUITextToSpeechTask import gtUITextToSpeechTask @@ -317,10 +329,10 @@ "Griptape Create: Agent": CreateAgent, "Griptape Create: Agent from Config": gtUICreateAgentFromConfig, "Griptape Run: Agent": RunAgent, - "Griptape Run: Prompt Task": gtUIPromptTask, - "Griptape Run: Text Summary": gtUITextSummaryTask, - "Griptape Run: Tool Task": gtUIToolTask, - "Griptape Run: Toolkit Task": gtUIToolkitTask, + "Griptape Run: Task": gtUITask, + # "Griptape Run: Prompt Task": gtUIPromptTask, + # "Griptape Run: Tool Task": gtUIToolTask, + # "Griptape Run: Toolkit Task": gtUIToolkitTask, # "Gt Run Agent": gtUIRunAgent, "Griptape Expand: Agent Nodes": ExpandAgent, "Griptape Set: Default Agent": gtUISetDefaultAgent, @@ -364,6 +376,7 @@ "Griptape Driver: Amazon Bedrock Stable Diffusion": gtUIAmazonBedrockStableDiffusionImageGenerationDriver, "Griptape Driver: Amazon Bedrock Titan": gtUIAmazonBedrockTitanImageGenerationDriver, "Griptape Driver: Azure OpenAI Image Generation": gtUIAzureOpenAiImageGenerationDriver, + "Griptape Driver: Black Forest Labs Image Generation": gtUIBlackForestImageGenerationDriver, "Griptape Driver: Leonardo.AI": gtUILeonardoImageGenerationDriver, "Griptape Driver: OpenAI Image Generation": gtUIOpenAiImageGenerationDriver, "Griptape Driver: OpenAI Compatible Image Generation": gtUIOpenAiCompatibleImageGenerationDriver, @@ -444,6 +457,7 @@ # Image "Griptape Create: Image from Text": gtUIPromptImageGenerationTask, "Griptape Create: Image Variation": gtUIPromptImageVariationTask, + "Griptape Create: Image Inpainting Variation": gtUIInpaintingImageGenerationTask, "Griptape Run: Image Description": gtUIImageQueryTask, "Griptape Run: Parallel Image Description": gtUIParallelImageQueryTask, "Griptape Load: Image From URL": gtUIFetchImage, @@ -456,6 +470,8 @@ "Griptape Combine: Merge Inputs": gtUIMergeInputs, "Griptape Load: Text": gtUILoadText, "Griptape Save: Text": gtUISaveText, + "Griptape Run: Text Extraction": gtUIExtractionTask, + "Griptape Run: Text Summary": gtUITextSummaryTask, "Griptape Vector Store: Add Text": gtUIVectorStoreUpsertTextTask, "Griptape Vector Store: Query": gtUIVectorStoreQueryTask, # "Griptape Display: Artifact": gtUIOutputArtifactNode, diff --git a/examples/Photographer-Workflow-Comparison-Example.json b/examples/Photographer-Workflow-Comparison-Example.json index 3d6f918..ebf2e78 100644 --- a/examples/Photographer-Workflow-Comparison-Example.json +++ b/examples/Photographer-Workflow-Comparison-Example.json @@ -5,14 +5,14 @@ { "id": 1, "type": "Griptape Create: Agent", - "pos": { - "0": 400, - "1": 50 - }, - "size": { - "0": 300, - "1": 156 - }, + "pos": [ + 400, + 50 + ], + "size": [ + 300, + 156 + ], "flags": {}, "order": 15, "mode": 0, @@ -20,22 +20,26 @@ { "name": "agent", "type": "AGENT", - "link": null + "link": null, + "shape": 7 }, { "name": "config", "type": "CONFIG", - "link": 51 + "link": 51, + "shape": 7 }, { "name": "tools", "type": "TOOL_LIST", - "link": null + "link": null, + "shape": 7 }, { "name": "rulesets", "type": "RULESET", - "link": 1 + "link": 1, + "shape": 7 }, { "name": "input_string", @@ -77,14 +81,14 @@ { "id": 2, "type": "Griptape Create: Rules", - "pos": { - "0": -100, - "1": 50 - }, - "size": { - "0": 400, - "1": 200 - }, + "pos": [ + -100, + 50 + ], + "size": [ + 400, + 200 + ], "flags": {}, "order": 0, "mode": 0, @@ -119,14 +123,14 @@ { "id": 3, "type": "Griptape Create: Rules", - "pos": { - "0": -100, - "1": 400 - }, - "size": { - "0": 400, - "1": 200 - }, + "pos": [ + -100, + 400 + ], + "size": [ + 400, + 200 + ], "flags": {}, "order": 1, "mode": 0, @@ -161,14 +165,14 @@ { "id": 5, "type": "Griptape Create: Agent", - "pos": { - "0": 400, - "1": 400 - }, - "size": { - "0": 300, - "1": 156 - }, + "pos": [ + 400, + 400 + ], + "size": [ + 300, + 156 + ], "flags": {}, "order": 16, "mode": 0, @@ -176,22 +180,26 @@ { "name": "agent", "type": "AGENT", - "link": null + "link": null, + "shape": 7 }, { "name": "config", "type": "CONFIG", - "link": 52 + "link": 52, + "shape": 7 }, { "name": "tools", "type": "TOOL_LIST", - "link": null + "link": null, + "shape": 7 }, { "name": "rulesets", "type": "RULESET", - "link": 2 + "link": 2, + "shape": 7 }, { "name": "input_string", @@ -232,14 +240,14 @@ { "id": 7, "type": "Griptape Create: Rules", - "pos": { - "0": -350, - "1": 1550 - }, - "size": { - "0": 672.3751220703125, - "1": 168.68878173828125 - }, + "pos": [ + -350, + 1550 + ], + "size": [ + 672.3751220703125, + 168.68878173828125 + ], "flags": {}, "order": 2, "mode": 0, @@ -274,14 +282,14 @@ { "id": 8, "type": "Griptape Create: Agent", - "pos": { - "0": 400, - "1": 1250 - }, - "size": { - "0": 300, - "1": 156.00003051757812 - }, + "pos": [ + 400, + 1250 + ], + "size": [ + 300, + 156.00003051757812 + ], "flags": {}, "order": 18, "mode": 0, @@ -289,22 +297,26 @@ { "name": "agent", "type": "AGENT", - "link": null + "link": null, + "shape": 7 }, { "name": "config", "type": "CONFIG", - "link": null + "link": null, + "shape": 7 }, { "name": "tools", "type": "TOOL_LIST", - "link": 11 + "link": 11, + "shape": 7 }, { "name": "rulesets", "type": "RULESET", - "link": 4 + "link": 4, + "shape": 7 }, { "name": "input_string", @@ -345,22 +357,23 @@ { "id": 12, "type": "Griptape Tool: WebSearch", - "pos": { - "0": -200, - "1": 1250 - }, - "size": { - "0": 315, - "1": 58 - }, + "pos": [ + -200, + 1250 + ], + "size": [ + 315, + 58 + ], "flags": {}, "order": 10, "mode": 0, "inputs": [ { "name": "driver", - "type": "DRIVER", - "link": 38 + "type": "WEB_SEARCH_DRIVER", + "link": 38, + "shape": 7 } ], "outputs": [ @@ -386,14 +399,14 @@ { "id": 14, "type": "Griptape Tool: WebScraper", - "pos": { - "0": -200, - "1": 1400 - }, - "size": { - "0": 315, - "1": 58 - }, + "pos": [ + -200, + 1400 + ], + "size": [ + 315, + 58 + ], "flags": {}, "order": 3, "mode": 0, @@ -421,14 +434,14 @@ { "id": 15, "type": "Griptape Combine: Tool List", - "pos": { - "0": 150, - "1": 1300 - }, - "size": { - "0": 226.8000030517578, - "1": 66 - }, + "pos": [ + 150, + 1300 + ], + "size": [ + 226.8000030517578, + 66 + ], "flags": {}, "order": 13, "mode": 0, @@ -436,7 +449,8 @@ { "name": "tool_1", "type": "TOOL_LIST", - "link": 9 + "link": 9, + "shape": 7 }, { "name": "tool_2", @@ -462,19 +476,20 @@ ], "properties": { "Node name for S&R": "Griptape Combine: Tool List" - } + }, + "widgets_values": [] }, { "id": 17, "type": "Griptape Convert: Agent to Tool", - "pos": { - "0": 750, - "1": 50 - }, - "size": { - "0": 400, - "1": 150 - }, + "pos": [ + 750, + 50 + ], + "size": [ + 400, + 150 + ], "flags": {}, "order": 19, "mode": 0, @@ -482,7 +497,8 @@ { "name": "agent", "type": "AGENT", - "link": 12 + "link": 12, + "shape": 7 } ], "outputs": [ @@ -510,14 +526,14 @@ { "id": 18, "type": "Griptape Convert: Agent to Tool", - "pos": { - "0": 750, - "1": 400 - }, - "size": { - "0": 400, - "1": 124 - }, + "pos": [ + 750, + 400 + ], + "size": [ + 400, + 124 + ], "flags": {}, "order": 20, "mode": 0, @@ -525,7 +541,8 @@ { "name": "agent", "type": "AGENT", - "link": 13 + "link": 13, + "shape": 7 } ], "outputs": [ @@ -553,14 +570,14 @@ { "id": 20, "type": "Griptape Convert: Agent to Tool", - "pos": { - "0": 750, - "1": 1250 - }, - "size": { - "0": 400, - "1": 124 - }, + "pos": [ + 750, + 1250 + ], + "size": [ + 400, + 124 + ], "flags": {}, "order": 22, "mode": 0, @@ -568,7 +585,8 @@ { "name": "agent", "type": "AGENT", - "link": 14 + "link": 14, + "shape": 7 } ], "outputs": [ @@ -596,16 +614,16 @@ { "id": 21, "type": "Griptape Create: Rules", - "pos": { - "0": 1450, - "1": 500 - }, - "size": { - "0": 400, - "1": 200 - }, + "pos": [ + 1450, + 500 + ], + "size": [ + 426.7962341308594, + 219.29710388183594 + ], "flags": {}, - "order": 4, + "order": 9, "mode": 0, "inputs": [], "outputs": [ @@ -630,7 +648,7 @@ }, "widgets_values": [ "Agent Rules", - "You have access to experts in their respective fields\nWork with the experts to get the results you need\nYou facilitate communication between them.\nIf they ask for feedback, you can provide it.\nAsk the expert on image prompting for the final prompt.\nOutput only the final image generation prompt. Do not wrap in markdown context." + "You are creating a prompot for an image generation engine.\nYou have access to topic experts in their respective fields\nWork with the experts to get the results you need\nYou facilitate communication between them.\nIf they ask for feedback, you can provide it.\nAsk the expert on image prompting for the final prompt.\nOutput only the final image generation prompt. Do not wrap in markdown context." ], "color": "#233", "bgcolor": "#355" @@ -638,14 +656,14 @@ { "id": 22, "type": "Griptape Create: Agent", - "pos": { - "0": 1950, - "1": 400 - }, - "size": { - "0": 397.9550476074219, - "1": 215.6602783203125 - }, + "pos": [ + 1950, + 400 + ], + "size": [ + 397.9550476074219, + 215.6602783203125 + ], "flags": { "pinned": true }, @@ -655,22 +673,26 @@ { "name": "agent", "type": "AGENT", - "link": null + "link": null, + "shape": 7 }, { "name": "config", "type": "CONFIG", - "link": null + "link": null, + "shape": 7 }, { "name": "tools", "type": "TOOL_LIST", - "link": 21 + "link": 21, + "shape": 7 }, { "name": "rulesets", "type": "RULESET", - "link": 16 + "link": 16, + "shape": 7 }, { "name": "input_string", @@ -712,14 +734,14 @@ { "id": 23, "type": "Griptape Combine: Tool List", - "pos": { - "0": 1450, - "1": 350 - }, - "size": { - "0": 250, - "1": 106 - }, + "pos": [ + 1450, + 350 + ], + "size": [ + 250, + 106 + ], "flags": {}, "order": 23, "mode": 0, @@ -727,7 +749,8 @@ { "name": "tool_1", "type": "TOOL_LIST", - "link": 17 + "link": 17, + "shape": 7 }, { "name": "tool_2", @@ -763,19 +786,65 @@ ], "properties": { "Node name for S&R": "Griptape Combine: Tool List" - } + }, + "widgets_values": [] + }, + { + "id": 24, + "type": "Griptape Display: Text", + "pos": [ + 2488.9990234375, + 494.4999694824219 + ], + "size": [ + 414.144287109375, + 217.94622802734375 + ], + "flags": {}, + "order": 25, + "mode": 0, + "inputs": [ + { + "name": "INPUT", + "type": "STRING", + "link": 39, + "widget": { + "name": "INPUT" + } + } + ], + "outputs": [ + { + "name": "OUTPUT", + "type": "STRING", + "links": [ + 24 + ], + "slot_index": 0, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "Griptape Display: Text" + }, + "widgets_values": [ + "", + "High-angle shot from above of a faded lavender-colored stuffed bunny with a torn and frayed pink satin bow, sitting on a vintage, ornate music box in a dimly lit antique shop. The bunny has glassy plastic eyes and a worn velvet patch on its left ear, giving it a soft, dreamy appearance. Captured with a Red Epic-W camera using an 85mm T1.8 lens, the image features muted colors with blue undertones and pastel shades of pale pink or baby blue, creating a nostalgic and ethereal atmosphere." + ], + "color": "#222", + "bgcolor": "#000" }, { "id": 25, "type": "Griptape Create: Image from Text", - "pos": { - "0": 2950, - "1": 400 - }, - "size": { - "0": 350, - "1": 150 - }, + "pos": [ + 2980.8017578125, + 393.39996337890625 + ], + "size": [ + 350, + 150 + ], "flags": {}, "order": 26, "mode": 0, @@ -783,12 +852,14 @@ { "name": "agent", "type": "AGENT", - "link": null + "link": null, + "shape": 7 }, { "name": "driver", "type": "DRIVER", - "link": 33 + "link": 33, + "shape": 7 }, { "name": "input_string", @@ -841,14 +912,14 @@ { "id": 26, "type": "Griptape Display: Image", - "pos": { - "0": 3550, - "1": 200 - }, - "size": { - "0": 1600, - "1": 950 - }, + "pos": [ + 3550, + 200 + ], + "size": [ + 1600, + 950 + ], "flags": {}, "order": 27, "mode": 0, @@ -856,7 +927,8 @@ { "name": "images", "type": "IMAGE", - "link": 25 + "link": 25, + "shape": 7 } ], "outputs": [ @@ -876,22 +948,23 @@ "properties": { "Node name for S&R": "Griptape Display: Image" }, + "widgets_values": [], "color": "#222", "bgcolor": "#000" }, { "id": 31, "type": "Griptape Driver: OpenAI Image Generation", - "pos": { - "0": 2500, - "1": 300 - }, - "size": { - "0": 400, - "1": 106 - }, + "pos": [ + 2500, + 300 + ], + "size": [ + 400, + 106 + ], "flags": {}, - "order": 5, + "order": 4, "mode": 0, "inputs": [], "outputs": [ @@ -919,16 +992,16 @@ { "id": 33, "type": "Griptape Create: Rules", - "pos": { - "0": -100, - "1": 800 - }, - "size": { - "0": 400, - "1": 200 - }, + "pos": [ + -100, + 800 + ], + "size": [ + 400, + 200 + ], "flags": {}, - "order": 6, + "order": 5, "mode": 0, "inputs": [], "outputs": [ @@ -961,14 +1034,14 @@ { "id": 34, "type": "Griptape Create: Agent", - "pos": { - "0": 400, - "1": 800 - }, - "size": { - "0": 300, - "1": 156 - }, + "pos": [ + 400, + 800 + ], + "size": [ + 300, + 156 + ], "flags": {}, "order": 17, "mode": 0, @@ -976,22 +1049,26 @@ { "name": "agent", "type": "AGENT", - "link": null + "link": null, + "shape": 7 }, { "name": "config", "type": "CONFIG", - "link": 53 + "link": 53, + "shape": 7 }, { "name": "tools", "type": "TOOL_LIST", - "link": null + "link": null, + "shape": 7 }, { "name": "rulesets", "type": "RULESET", - "link": 34 + "link": 34, + "shape": 7 }, { "name": "input_string", @@ -1032,14 +1109,14 @@ { "id": 35, "type": "Griptape Convert: Agent to Tool", - "pos": { - "0": 750, - "1": 800 - }, - "size": { - "0": 400, - "1": 124 - }, + "pos": [ + 750, + 800 + ], + "size": [ + 400, + 124 + ], "flags": {}, "order": 21, "mode": 0, @@ -1047,7 +1124,8 @@ { "name": "agent", "type": "AGENT", - "link": 35 + "link": 35, + "shape": 7 } ], "outputs": [ @@ -1075,22 +1153,22 @@ { "id": 36, "type": "Griptape WebSearch Driver: DuckDuckGo", - "pos": { - "0": -590, - "1": 1249 - }, - "size": { - "0": 310.79998779296875, - "1": 26 - }, + "pos": [ + -590, + 1249 + ], + "size": [ + 310.79998779296875, + 26 + ], "flags": {}, - "order": 7, + "order": 6, "mode": 0, "inputs": [], "outputs": [ { "name": "DRIVER", - "type": "DRIVER", + "type": "WEB_SEARCH_DRIVER", "links": [ 38 ], @@ -1101,20 +1179,21 @@ "properties": { "Node name for S&R": "Griptape Driver: DuckDuckGo WebSearch" }, + "widgets_values": [], "color": "#233", "bgcolor": "#355" }, { "id": 38, "type": "Griptape Create: Image from Text", - "pos": { - "0": 1700, - "1": -1150 - }, - "size": { - "0": 350, - "1": 150 - }, + "pos": [ + 1700, + -1150 + ], + "size": [ + 350, + 150 + ], "flags": {}, "order": 11, "mode": 0, @@ -1122,12 +1201,14 @@ { "name": "agent", "type": "AGENT", - "link": null + "link": null, + "shape": 7 }, { "name": "driver", "type": "DRIVER", - "link": 43 + "link": 43, + "shape": 7 }, { "name": "input_string", @@ -1181,16 +1262,16 @@ { "id": 39, "type": "Griptape Driver: OpenAI Image Generation", - "pos": { - "0": 1200, - "1": -1150 - }, - "size": { - "0": 400, - "1": 106 - }, + "pos": [ + 1200, + -1150 + ], + "size": [ + 400, + 106 + ], "flags": {}, - "order": 8, + "order": 7, "mode": 0, "inputs": [], "outputs": [ @@ -1218,14 +1299,14 @@ { "id": 40, "type": "Griptape Display: Image", - "pos": { - "0": 2200, - "1": -1250 - }, - "size": { - "0": 1450, - "1": 850 - }, + "pos": [ + 2200, + -1250 + ], + "size": [ + 1450, + 850 + ], "flags": {}, "order": 14, "mode": 0, @@ -1233,7 +1314,8 @@ { "name": "images", "type": "IMAGE", - "link": 42 + "link": 42, + "shape": 7 } ], "outputs": [ @@ -1253,60 +1335,23 @@ "properties": { "Node name for S&R": "Griptape Display: Image" }, + "widgets_values": [], "color": "#222", "bgcolor": "#000" }, - { - "id": 43, - "type": "Reroute", - "pos": { - "0": -375, - "1": 500 - }, - "size": [ - 90.4, - 26 - ], - "flags": {}, - "order": 12, - "mode": 0, - "inputs": [ - { - "name": "", - "type": "*", - "link": 50 - } - ], - "outputs": [ - { - "name": "CONFIG", - "type": "CONFIG", - "links": [ - 51, - 52, - 53 - ], - "slot_index": 0 - } - ], - "properties": { - "showOutputText": true, - "horizontal": false - } - }, { "id": 42, "type": "Griptape Agent Config: Ollama Drivers", - "pos": { - "0": -900, - "1": 500 - }, - "size": { - "0": 466.1999816894531, - "1": 322 - }, + "pos": [ + -900, + 500 + ], + "size": [ + 466.1999816894531, + 332 + ], "flags": {}, - "order": 9, + "order": 8, "mode": 0, "inputs": [], "outputs": [ @@ -1316,8 +1361,8 @@ "links": [ 50 ], - "shape": 3, - "slot_index": 0 + "slot_index": 0, + "shape": 3 } ], "properties": { @@ -1341,49 +1386,42 @@ "bgcolor": "#3f5159" }, { - "id": 24, - "type": "Griptape Display: Text", - "pos": { - "0": 2500, - "1": 500 - }, - "size": { - "0": 400, - "1": 200 - }, + "id": 43, + "type": "Reroute", + "pos": [ + -375, + 500 + ], + "size": [ + 90.4000015258789, + 26 + ], "flags": {}, - "order": 25, + "order": 12, "mode": 0, "inputs": [ { - "name": "INPUT", - "type": "STRING", - "link": 39, - "widget": { - "name": "INPUT" - } + "name": "", + "type": "*", + "link": 50 } ], "outputs": [ { - "name": "OUTPUT", - "type": "STRING", + "name": "CONFIG", + "type": "CONFIG", "links": [ - 24 + 51, + 52, + 53 ], - "slot_index": 0, - "shape": 3 + "slot_index": 0 } ], "properties": { - "Node name for S&R": "Griptape Display: Text" - }, - "widgets_values": [ - "", - "" - ], - "color": "#222", - "bgcolor": "#000" + "showOutputText": true, + "horizontal": false + } } ], "links": [ @@ -1614,6 +1652,7 @@ ], "groups": [ { + "id": 1, "title": "Cinematographer", "bounding": [ -150, @@ -1626,6 +1665,7 @@ "flags": {} }, { + "id": 2, "title": "Color Theorist", "bounding": [ -150, @@ -1638,6 +1678,7 @@ "flags": {} }, { + "id": 3, "title": "Detail Enthusiast", "bounding": [ -150, @@ -1650,6 +1691,7 @@ "flags": {} }, { + "id": 4, "title": "Image Prompt Expert", "bounding": [ -650, @@ -1662,6 +1704,7 @@ "flags": {} }, { + "id": 5, "title": "Ollama Llama3", "bounding": [ -925, @@ -1674,6 +1717,7 @@ "flags": {} }, { + "id": 6, "title": "Organizer Agent", "bounding": [ 1400, @@ -1686,18 +1730,20 @@ "flags": {} }, { + "id": 7, "title": "Image Generation", "bounding": [ 2450, 200, - 900, - 550 + 924.6339111328125, + 550.8701171875 ], "color": "#b06634", "font_size": 24, "flags": {} }, { + "id": 8, "title": "Generic Image Prompt", "bounding": [ 1150, @@ -1713,10 +1759,10 @@ "config": {}, "extra": { "ds": { - "scale": 0.4665073802097334, + "scale": 0.5644739300537773, "offset": [ - 176.93557320818041, - 1448.9823541881826 + -848.1325481151173, + 359.3482043102513 ] }, "info": { diff --git a/examples/Photographer-Workflow-Comparison-Example.png b/examples/Photographer-Workflow-Comparison-Example.png index b07e17c..a6ea1f9 100644 Binary files a/examples/Photographer-Workflow-Comparison-Example.png and b/examples/Photographer-Workflow-Comparison-Example.png differ diff --git a/examples/README.md b/examples/README.md index 5ce9311..b92c165 100644 --- a/examples/README.md +++ b/examples/README.md @@ -6,10 +6,36 @@ This workflow demonstrates all the options for creating an agent based on variou ![Agent Configuration](Griptape-Agent-Config.png) Download: [Griptape-Agent-Config.json](Griptape-Agent-Config.json) +## Render Log Review +It's handy to be able to review render logs and quickly understand your next actions to resolve any errors. In this example, Griptape uses Anthropic Claude Sonnet-3.5 to review an Autodesk Maya render log and return a summary of errors and recommended next actions. + +![Maya Render Log](render_log_review.png) +Download: [render_log_review.png](render_log_review.png) + +## Black Forest Labs - Flux Pro 1.1 Image Generation +Use Black Forest Labs Flux models with Griptape! + +![BFL Flux-Pro-1.1](griptape_black_forest_labs_create_image.png) +Download: [griptape_black_forest_labs_create_image.png](griptape_black_forest_labs_create_image.png) + +## Black Forest Labs - Flux Pro 1.0-Canny - Image Variation + +Use Black Forest Labs Flux-Pro-1.0-canny with Griptape to create a variation on an image. + +![BFL flux-pro-1.0-canny](griptape_black_forest_labs_create_variation.png) +Download: [griptape_black_forest_labs_create_variation.png](griptape_black_forest_labs_create_variation.png) + +## Black Forest Labs - Flux Pro 1.0-Fill - Image Inpainting + +Use Black Forest Labs Flux-Pro-1.0-fill with Griptape to perform inpainting on an image. + +![BFL flux-pro-1.0-fill](griptape_black_forest_flux_inpainting.png) +Download: [griptape_black_forest_flux_inpainting.png](griptape_black_forest_flux_inpainting.png) + ## Griptape Expert Photographers Use Agents as experts in their field to help provide feedback that will generate more advanced outputs. Utilizes multiple models - including Ollama running locally. If you don't have Ollama installed, feel free to use another `prompt_driver`. -![Expert Photographer](Photographer-Workflow-Comparison-Example.json) +![Expert Photographer](Photographer-Workflow-Comparison-Example.png) Download: [Photographer-Workflow-Comparison-Example.json](Photographer-Workflow-Comparison-Example.json) ## Text to Speech @@ -18,7 +44,7 @@ This example includes two workflows - one which is a simple Text To Speech conve ![Text To Speech](Griptape-Text-to-Speech.png) Download: [Griptape-Text-to-Speech.json](Griptape-Text-to-Speech.json) -## Off Promopt +## Off Prompt This example demonstrates how to use a local model (`llama3.1` in this case) to handle all of the results from the `WebScraper` tool. ![Off Prompt](OffPrompt.png) diff --git a/examples/griptape_black_forest_flux_inpainting.png b/examples/griptape_black_forest_flux_inpainting.png new file mode 100644 index 0000000..b4dd900 Binary files /dev/null and b/examples/griptape_black_forest_flux_inpainting.png differ diff --git a/examples/griptape_black_forest_labs_create_image.png b/examples/griptape_black_forest_labs_create_image.png new file mode 100644 index 0000000..86ade7f Binary files /dev/null and b/examples/griptape_black_forest_labs_create_image.png differ diff --git a/examples/griptape_black_forest_labs_create_variation.png b/examples/griptape_black_forest_labs_create_variation.png new file mode 100644 index 0000000..50a35ed Binary files /dev/null and b/examples/griptape_black_forest_labs_create_variation.png differ diff --git a/examples/pdf/resume.pdf b/examples/pdf/resume.pdf new file mode 100644 index 0000000..48b11d9 Binary files /dev/null and b/examples/pdf/resume.pdf differ diff --git a/examples/render_log_review.png b/examples/render_log_review.png new file mode 100644 index 0000000..b0f5c54 Binary files /dev/null and b/examples/render_log_review.png differ diff --git a/examples/text/drone_operation_settings.json b/examples/text/drone_operation_settings.json new file mode 100644 index 0000000..4dafe90 --- /dev/null +++ b/examples/text/drone_operation_settings.json @@ -0,0 +1,40 @@ +{ + "drone_model": "LH-450", + "operation_modes": { + "standard": { + "battery_usage_rate": "medium", + "visibility": "60%", + "hovering_speed": "20 km/h", + "sensors": ["thermal_imagery", "biometric_scanner"] + }, + "stealth": { + "battery_usage_rate": "low", + "visibility": "10%", + "hovering_speed": "10 km/h", + "sensors": ["biometric_scanner"] + }, + "pursuit": { + "battery_usage_rate": "high", + "visibility": "90%", + "hovering_speed": "40 km/h", + "sensors": ["thermal_imagery", "extraterrestrial_life_detector"] + } + }, + "emergency_shutdown": { + "triggers": [ + "battery < 10%", + "device_overheat", + "external tampering" + ], + "actions": [ + "initiate_return_to_base", + "emit distress signal", + "self_destruct_sequence" + ] + }, + "maintenance_schedule": { + "battery_replacement": "every 100 flight hours", + "sensor_calibration": "every 50 flight hours", + "external casing inspection": "every 30 flight hours" + } +} diff --git a/examples/text/letter_application.txt b/examples/text/letter_application.txt new file mode 100644 index 0000000..ad9fd8f --- /dev/null +++ b/examples/text/letter_application.txt @@ -0,0 +1,21 @@ +123 Applicant Lane +Jobtown, JT 12345 +January 15, 2024 + +Hiring Manager +Innovation Tech Inc. +456 Opportunity Ave +Jobtown, JT 12345 + +Dear Hiring Manager, + +I am writing to apply for the Software Developer position at Innovation Tech Inc. advertised on your website. With a Bachelor’s degree in Computer Science and three years of experience in full-stack development, I am excited about the opportunity to bring my technical skills and enthusiasm for problem-solving to your team. + +In my previous role at NextGen Solutions, I developed and maintained web applications that improved user engagement by over 25%. I am particularly skilled in JavaScript, Python, and React, and have experience working in agile teams to deliver high-quality products. + +Thank you for considering my application. I look forward to the opportunity to discuss how my background, skills, and passion for technology align with the goals of Innovation Tech Inc. + +Sincerely, +Jamie Smith +jamie.smith@email.com +(321) 654-9870 diff --git a/examples/text/letter_camp.txt b/examples/text/letter_camp.txt new file mode 100644 index 0000000..e953261 --- /dev/null +++ b/examples/text/letter_camp.txt @@ -0,0 +1,13 @@ +Camp Greenlake +July 15, 2024 + +Dear Mom and Dad, + +Greetings from Camp Greenlake! I’m not saying this place has a mosquito problem, but let’s just say I’ve started naming them. So far, my bunkmate and I have survived three days of mystery meat, one epic hike, and one talent show that could’ve used some serious improvement. + +We went canoeing yesterday, and I only tipped over twice! I also discovered that the lake is… well, more of a pond. But it’s all good! Next week we’re supposed to go on a “survival skills” campout, so keep your phones on and ready for a possible SOS. + +Miss you guys! Send snacks if you can, and tell Muffin the dog I miss her more than camp food! + +Love, +Ben diff --git a/examples/text/letter_customer_complaint.txt b/examples/text/letter_customer_complaint.txt new file mode 100644 index 0000000..db1e599 --- /dev/null +++ b/examples/text/letter_customer_complaint.txt @@ -0,0 +1,21 @@ +789 Frustration Street +Cityville, CV 54321 +February 10, 2024 + +Customer Service Department +QuickFix Electronics +101 Appliance Lane +Cityville, CV 54321 + +Dear QuickFix Customer Service, + +I am writing to express my disappointment with a recent purchase from your store. On January 30, I bought a “Zappy Blender Pro” model, which unfortunately stopped working after just one week of use. + +I followed all recommended instructions for use and maintenance, so I was surprised and frustrated by this failure. I returned to the store, only to find that my warranty was not recognized due to a “clerical issue.” I am requesting either a full refund or a replacement for the blender, as I believe this is a reasonable resolution. + +I look forward to your prompt response and a satisfactory resolution. Thank you for your attention to this matter. + +Sincerely, +Alex Green +alex.green@email.com +(987) 654-3210 diff --git a/examples/text/letter_grandma.txt b/examples/text/letter_grandma.txt new file mode 100644 index 0000000..732cfaa --- /dev/null +++ b/examples/text/letter_grandma.txt @@ -0,0 +1,10 @@ +Dear Grandma, + +I hope you’re doing well! I miss you and all the little things you do to make everyone feel at home. Mom told me you made your famous apple pie last week—I swear I could smell it all the way over here! + +Things have been busy here, but I’m enjoying my classes and even joined the gardening club. Who would’ve thought I’d inherit your green thumb? I’ve been growing a little basil plant, though it’s nowhere near as amazing as your backyard garden. + +Can’t wait to come visit soon! Give my love to Grandpa, and please save me a slice of that pie if you make it again. + +Love, +Lucy diff --git a/examples/text/letter_information_request.txt b/examples/text/letter_information_request.txt new file mode 100644 index 0000000..73cd633 --- /dev/null +++ b/examples/text/letter_information_request.txt @@ -0,0 +1,22 @@ +222 Researcher Ave +Scholar City, SC 33333 +March 1, 2024 + +Archives Department +National Library +555 Knowledge Blvd +Scholar City, SC 33333 + +Dear Archives Department, + +I am a postgraduate student at Scholar University researching historical records from the late 19th century, particularly related to immigration patterns. I understand that the National Library holds collections from this period and am interested in accessing relevant documents, letters, and records. + +Could you please provide information regarding the availability of these records, as well as any necessary permissions or procedures for accessing them? Any guidance you can offer would be greatly appreciated. + +Thank you for your assistance in furthering my research. + +Sincerely, +Dr. Alice Yang +Postgraduate Researcher +Scholar University +alice.yang@scholar.edu diff --git a/examples/text/life_detection_device_inventory.json b/examples/text/life_detection_device_inventory.json new file mode 100644 index 0000000..b73fc25 --- /dev/null +++ b/examples/text/life_detection_device_inventory.json @@ -0,0 +1,299 @@ +{ + "devices": [ + { + "id": "LDD-001", + "name": "Biometric Scanner", + "description": "Detects biological signals within a 500-meter radius", + "capabilities": { + "detection_radius": "500 meters", + "energy_consumption": "medium", + "target_types": [ + "mammalian", + "reptilian", + "unknown life forms" + ] + }, + "settings": { + "sensitivity_levels": [ + "low", + "medium", + "high" + ], + "scan_modes": [ + { + "name": "Wide Area", + "time_to_scan": "10 minutes", + "energy_usage": "20%" + }, + { + "name": "Focused", + "time_to_scan": "2 minutes", + "energy_usage": "10%" + } + ] + } + }, + { + "id": "LDD-002", + "name": "Extraterrestrial Life Detector", + "description": "Analyzes air samples for non-earthlike microbes", + "capabilities": { + "sample_types": [ + "air", + "soil" + ], + "analysis_duration": "5 minutes", + "target_rarity": "extraterrestrial only" + }, + "settings": { + "isotope_detection": true, + "radiation_filtering": true, + "alarm_levels": { + "trace_found": "yellow", + "significant_presence": "red" + } + } + }, + { + "id": "LDD-003", + "name": "Thermal Imagery Analyzer", + "description": "Detects heat signatures of life forms in low-light areas", + "capabilities": { + "detection_radius": "1 km", + "energy_consumption": "high", + "detection_types": [ + "warm-blooded life forms", + "heat anomalies" + ] + }, + "settings": { + "thermal_resolution": "high", + "modes": [ + "infrared", + "ultraviolet" + ], + "data_storage_limit": "500 images" + } + }, + { + "id": "LDD-004", + "name": "Quantum Signature Scanner", + "description": "Detects quantum entanglement patterns unique to advanced lifeforms", + "capabilities": { + "detection_radius": "50 meters", + "energy_consumption": "very high", + "scan_depth": "subatomic", + "target_types": [ + "quantum anomalies", + "dimensional rifts" + ] + }, + "settings": { + "entanglement_threshold": "0.001%", + "quantum_noise_filter": true, + "dimensional_calibration": { + "base_dimension": "3D", + "detection_dimensions": "11D" + } + } + }, + { + "id": "LDD-005", + "name": "Underwater Biosensor Array", + "description": "Monitors aquatic life signatures in deep water environments", + "capabilities": { + "max_depth": "10000 meters", + "pressure_tolerance": "1100 bar", + "detection_types": [ + "bioluminescence", + "electrical signals", + "acoustic patterns" + ] + }, + "settings": { + "depth_zones": [ + "surface", + "twilight", + "midnight", + "abyssal" + ], + "salinity_compensation": true, + "pressure_calibration": "automatic" + } + }, + { + "id": "LDD-006", + "name": "Neural Pattern Detector", + "description": "Identifies complex neural activity patterns indicating consciousness", + "capabilities": { + "detection_radius": "25 meters", + "energy_consumption": "medium", + "pattern_recognition": [ + "basic consciousness", + "hive mind activity", + "distributed intelligence" + ] + }, + "settings": { + "consciousness_threshold": "0.75", + "filter_modes": [ + "individual", + "collective", + "hybrid" + ], + "signal_processing": "adaptive" + } + }, + { + "id": "LDD-007", + "name": "Atmospheric Composition Analyzer", + "description": "Detects life-supporting atmospheric conditions", + "capabilities": { + "detection_range": "atmosphere", + "analysis_speed": "real-time", + "compound_detection": [ + "oxygen", + "nitrogen", + "carbon dioxide", + "methane" + ] + }, + "settings": { + "detection_threshold": "1 ppm", + "sample_frequency": "continuous", + "atmospheric_layers": [ + "troposphere", + "stratosphere", + "mesosphere" + ] + } + }, + { + "id": "LDD-008", + "name": "Temporal Biosignature Scanner", + "description": "Detects biological traces across different timeframes", + "capabilities": { + "temporal_range": "1000 years", + "energy_consumption": "extreme", + "scan_modes": [ + "past", + "present", + "probability-future" + ] + }, + "settings": { + "temporal_resolution": "1 day", + "probability_threshold": "85%", + "timeline_lock": true, + "paradox_prevention": "active" + } + }, + { + "id": "LDD-009", + "name": "Subterranean Life Detector", + "description": "Identifies life forms in underground environments", + "capabilities": { + "penetration_depth": "2000 meters", + "substrate_types": [ + "rock", + "soil", + "magma" + ], + "detection_methods": [ + "seismic", + "chemical", + "electromagnetic" + ] + }, + "settings": { + "depth_intervals": "50 meters", + "geological_filter": true, + "movement_tracking": "enabled" + } + }, + { + "id": "LDD-010", + "name": "Plasma Life Form Detector", + "description": "Specialized in detecting energy-based life forms", + "capabilities": { + "energy_spectrum": "full electromagnetic", + "detection_radius": "750 meters", + "plasma_sensitivity": "ultra-high", + "target_types": [ + "energy beings", + "plasma entities", + "electromagnetic life" + ] + }, + "settings": { + "energy_threshold": "1 microjoule", + "containment_field": "active", + "spectrum_analysis": "continuous" + } + }, + { + "id": "LDD-011", + "name": "Silicon-Based Life Detector", + "description": "Detects non-carbon-based life forms", + "capabilities": { + "detection_radius": "300 meters", + "energy_consumption": "low", + "target_composition": [ + "silicon", + "germanium", + "boron" + ] + }, + "settings": { + "molecular_resolution": "0.1 nanometer", + "temperature_range": { + "min": "0K", + "max": "500K" + }, + "crystal_structure_analysis": true + } + }, + { + "id": "LDD-012", + "name": "Dimensional Shift Detector", + "description": "Monitors for life forms crossing dimensional boundaries", + "capabilities": { + "detection_radius": "100 meters", + "dimension_sensitivity": "multi-verse", + "energy_consumption": "extreme", + "detection_types": [ + "phase shifts", + "dimensional tears", + "reality fluctuations" + ] + }, + "settings": { + "dimensional_calibration": "auto", + "reality_anchor": true, + "breach_protocols": { + "detection": "immediate", + "containment": "automatic" + } + } + }, + { + "id": "LDD-013", + "name": "Micro-Gravity Life Scanner", + "description": "Specialized in detecting life adapted to zero-G environments", + "capabilities": { + "detection_radius": "200 meters", + "gravity_sensitivity": "zero to near-zero", + "target_behaviors": [ + "flotation patterns", + "vacuum adaptation", + "radiation resistance" + ] + }, + "settings": { + "gravity_threshold": "0.001 G", + "vacuum_compensation": true, + "movement_analysis": "3D tracking" + } + } + ] +} \ No newline at end of file diff --git a/examples/text/mission_config.json b/examples/text/mission_config.json new file mode 100644 index 0000000..4c1d0fb --- /dev/null +++ b/examples/text/mission_config.json @@ -0,0 +1,47 @@ +{ + "mission": { + "name": "Life Hunter", + "objective": "Search for life forms in post-apocalyptic wasteland", + "settings": { + "environment": { + "temperature_range": [-50, 50], + "terrain_types": ["desert", "ruins", "toxic swamp"], + "radiation_level": "high", + "daylight_hours": 8 + }, + "drone_parameters": { + "max_flight_time": "24 hours", + "battery_type": "Plasma Battery Pack", + "hovering_altitude": "200 meters", + "communication_range": { + "earth_signals": "5 km", + "extraterrestrial_signals": "infinite" + }, + "navigation_modes": [ + { + "name": "Stealth", + "visibility": "0%", + "energy_consumption": "low" + }, + { + "name": "High-Speed Pursuit", + "visibility": "80%", + "energy_consumption": "high" + } + ] + } + } + }, + "emergency_protocols": { + "return_to_base": { + "trigger_conditions": ["battery < 20%", "extreme weather"], + "navigation_mode": "Stealth", + "communication_channel": "emergency" + }, + "self_destruct": { + "trigger_conditions": ["captured by hostile force", "unable to complete mission"], + "delay": "10 seconds", + "authorization_required": true + } + } +} diff --git a/examples/text/mission_logs.json b/examples/text/mission_logs.json new file mode 100644 index 0000000..74af36e --- /dev/null +++ b/examples/text/mission_logs.json @@ -0,0 +1,88 @@ +{ + "mission_logs": [ + { + "timestamp": "2024-02-15T08:30:00Z", + "location": { + "coordinates": { + "latitude": 35.6895, + "longitude": 139.6917 + }, + "terrain": "toxic swamp" + }, + "event": "initial scan", + "sensor_data": { + "biometric_scanner": { + "detected": true, + "life_signs": [ + { + "type": "unknown", + "signal_strength": "medium", + "distance": "300 meters" + } + ] + }, + "thermal_imagery": { + "temperature_anomalies": [ + { + "area": "north quadrant", + "temperature": 42, + "size": "small" + }, + { + "area": "east quadrant", + "temperature": 58, + "size": "medium" + } + ] + } + } + }, + { + "timestamp": "2024-02-15T10:00:00Z", + "location": { + "coordinates": { + "latitude": 35.7000, + "longitude": 139.7050 + }, + "terrain": "ruins" + }, + "event": "life form detected", + "sensor_data": { + "biometric_scanner": { + "detected": true, + "life_signs": [ + { + "type": "mammalian", + "signal_strength": "high", + "distance": "100 meters" + } + ] + }, + "extraterrestrial_life_detector": { + "air_sample_analysis": { + "result": "positive", + "trace_elements": ["Xenon", "Krypton"] + } + } + } + }, + { + "timestamp": "2024-02-15T12:30:00Z", + "location": { + "coordinates": { + "latitude": 35.7100, + "longitude": 139.7100 + }, + "terrain": "desert" + }, + "event": "system malfunction", + "sensor_data": { + "error_report": { + "device": "biometric_scanner", + "error_type": "overheat", + "suggested_action": "cool down device" + } + } + } + ] +} diff --git a/examples/text/movie_titles_fake.tsv b/examples/text/movie_titles_fake.tsv new file mode 100644 index 0000000..9750257 --- /dev/null +++ b/examples/text/movie_titles_fake.tsv @@ -0,0 +1,51 @@ +tconst titleType primaryTitle originalTitle isAdult startYear endYear runtimeMinutes genres +tt0000001 short "Carmencita" "Carmencita" 0 1894 \N 1 Documentary,Short +tt0000002 short "Le clown et ses chiens" "Le clown et ses chiens" 0 1892 \N 5 Animation,Short +tt0000003 movie "Pauvre Pierrot" "Pauvre Pierrot" 0 1892 \N 4 Animation,Comedy,Romance +tt0000004 short "Un bon bock" "Un bon bock" 0 1892 \N 12 Animation,Short +tt0000005 short "Blacksmith Scene" "Blacksmith Scene" 0 1893 \N 1 Comedy,Short +tt0000006 short "Chinese Opium Den" "Chinese Opium Den" 0 1894 \N 2 Short +tt0000007 short "Corbett and Courtney Before the Kinetograph" "Corbett and Courtney Before the Kinetograph" 0 1894 \N 1 Documentary,Short,Sport +tt0000008 short "Edison Kinetoscopic Record of a Sneeze" "Edison Kinetoscopic Record of a Sneeze" 0 1894 \N 1 Documentary,Short +tt0000009 movie "Miss Jerry" "Miss Jerry" 0 1894 \N 45 Comedy,Romance +tt0000010 short "The Old Violin" "The Old Violin" 0 1894 \N 2 Short +tt0000011 short "Exiting the Factory" "Exiting the Factory" 0 1895 \N 1 Documentary,Short +tt0000012 short "Rough Sea at Dover" "Rough Sea at Dover" 0 1895 \N 1 Documentary,Short +tt0000013 short "The Enchanted Drawing" "The Enchanted Drawing" 0 1900 \N 2 Comedy,Fantasy,Short +tt0000014 short "The Sick Kitten" "The Sick Kitten" 0 1903 \N 1 Comedy,Family,Short +tt0000015 movie "The Great Train Robbery" "The Great Train Robbery" 0 1903 \N 12 Action,Adventure,Western +tt0000016 short "The Escaped Lunatic" "The Escaped Lunatic" 0 1904 \N 3 Comedy,Horror,Short +tt0000017 short "The Automobile Thieves" "The Automobile Thieves" 0 1906 \N 7 Action,Crime,Short +tt0000018 short "Dream of a Rarebit Fiend" "Dream of a Rarebit Fiend" 0 1906 \N 7 Comedy,Fantasy,Short +tt0000019 short "The 'Teddy' Bears" "The 'Teddy' Bears" 0 1907 \N 13 Animation,Comedy,Short +tt0000020 movie "Ben Hur" "Ben Hur" 0 1907 \N 15 Adventure,Drama,History +tt0000021 short "Adventures of Dollie" "Adventures of Dollie" 0 1908 \N 12 Drama,Short +tt0000022 short "Rescued from an Eagle's Nest" "Rescued from an Eagle's Nest" 0 1908 \N 7 Drama,Short +tt0000023 movie "The Life of Moses" "The Life of Moses" 0 1909 \N 90 Biography,Drama,History +tt0000024 short "The Red Man and the Child" "The Red Man and the Child" 0 1908 \N 11 Drama,Short +tt0000025 movie "A Christmas Carol" "A Christmas Carol" 0 1908 \N 15 Drama,Fantasy +tt0000026 short "The Lonedale Operator" "The Lonedale Operator" 0 1911 \N 17 Action,Crime,Drama +tt0000027 short "An Unseen Enemy" "An Unseen Enemy" 0 1912 \N 17 Crime,Drama,Short +tt0000028 movie "The Musketeers of Pig Alley" "The Musketeers of Pig Alley" 0 1912 \N 17 Crime,Drama +tt0000029 short "The New York Hat" "The New York Hat" 0 1912 \N 16 Drama,Short +tt0000030 movie "The Birth of a Nation" "The Birth of a Nation" 0 1915 \N 187 Drama,History,War +tt0000031 short "The Tramp" "The Tramp" 0 1915 \N 26 Comedy,Drama,Short +tt0000032 short "The Immigrant" "The Immigrant" 0 1917 \N 24 Comedy,Drama,Short +tt0000033 movie "The Kid" "The Kid" 0 1921 \N 68 Comedy,Drama,Family +tt0000034 movie "Dr. Mabuse: The Gambler" "Dr. Mabuse: The Gambler" 0 1922 \N 271 Crime,Thriller +tt0000035 short "Safety Last!" "Safety Last!" 0 1923 \N 70 Comedy,Thriller +tt0000036 movie "Nosferatu" "Nosferatu" 0 1922 \N 94 Fantasy,Horror +tt0000037 movie "Metropolis" "Metropolis" 0 1927 \N 153 Drama,Sci-Fi +tt0000038 short "Steamboat Willie" "Steamboat Willie" 0 1928 \N 8 Animation,Comedy,Family +tt0000039 short "Un chien andalou" "Un chien andalou" 0 1929 \N 21 Fantasy,Horror,Short +tt0000040 movie "Frankenstein" "Frankenstein" 0 1931 \N 71 Drama,Horror,Sci-Fi +tt0000041 movie "The Invisible Man" "The Invisible Man" 0 1933 \N 71 Horror,Sci-Fi +tt0000042 movie "It Happened One Night" "It Happened One Night" 0 1934 \N 105 Comedy,Romance +tt0000043 movie "Modern Times" "Modern Times" 0 1936 \N 87 Comedy,Drama +tt0000044 movie "Snow White and the Seven Dwarfs" "Snow White and the Seven Dwarfs" 0 1937 \N 83 Animation,Family,Fantasy +tt0000045 movie "Casablanca" "Casablanca" 0 1942 \N 102 Drama,Romance,War +tt0000046 movie "Citizen Kane" "Citizen Kane" 0 1941 \N 119 Drama,Mystery +tt0000047 movie "Notorious" "Notorious" 0 1946 \N 102 Film-Noir,Romance,Thriller +tt0000048 movie "12 Angry Men" "12 Angry Men" 0 1957 \N 96 Crime,Drama +tt0000049 movie "Ben-Hur" "Ben-Hur" 0 1959 \N 212 Adventure,Drama,History +tt0000050 movie "Psycho" "Psycho" 0 1960 \N 109 Horror,Mystery,Thriller diff --git a/examples/text/resume.docx b/examples/text/resume.docx new file mode 100644 index 0000000..6483fad Binary files /dev/null and b/examples/text/resume.docx differ diff --git a/examples/text/resume.md b/examples/text/resume.md new file mode 100644 index 0000000..adff8ac --- /dev/null +++ b/examples/text/resume.md @@ -0,0 +1,36 @@ +# RX-73 Cleanup Unit + +## Professional Objective +A resilient, dust-resistant bot seeking opportunities in environmental restoration to transform debris-strewn wastelands into inhabitable spaces. Armed with laser precision, a high-powered vacuum, and an undying loyalty to cleaner landscapes. + +## Experience + +### Senior Debris Removal Specialist +**Sector 7, Rubble Valley (2051–2062)** +* **Primary Task**: Relocated over 20 tons of debris from Sector 7, specializing in heavy metal shrapnel and residual sludge +* **Detail-Oriented Operations**: Programmed for recognizing high-priority hazards such as rusted spikes, sharp metal shards, and hazardous sludge for safe extraction and disposal +* **Efficient Mobility**: Traversed shifting sand dunes, fractured concrete, and wasteland ravines with optimized energy conservation and minimal wear +* **Complaint Management**: Frequently interfaced with stray animals and scavengers in a friendly, non-threatening manner, reducing hostilities by 70% + +### Toxic Waste Neutralization Associate +**Great Divide Toxic Spill, North Quadrant (2047–2051)** +* **Toxin Reduction**: Deployed toxin-absorbent pads across 15 acres of acid pools, achieving a 90% reduction in toxic fumes within 6 months +* **Chemical Compatibility**: Equipped with acid-resistant shell; performed scrubbing cycles in high-acidity zones without component degradation +* **Emergency Shutdown Protocols**: Experienced in over 50 auto-shutdown rescues when heat or toxic levels reached critical thresholds + +## Skills +* **Precision Cleanup**: Equipped with vacuum and hydraulic claws for thorough debris removal +* **Stamina**: 48-hour battery life on a single charge, adaptable to both solar and kinetic recharge +* **Hazard Identification**: Recognizes corrosive materials, toxins, and radiation to ensure safe navigation and cleanup +* **Interfacing Compatibility**: Functions as a communication liaison with human teams and fellow bots in hazardous zones + +## Technical Specifications +* **Model**: RX-73 Cleanup Unit +* **Durability**: Enhanced corrosion resistance with reinforced steel joints +* **Software**: Version 9.2 Hazard and Toxin Recognition +* **Power Supply**: Lithium Ion + Solar Charging Capability + +## Education & Training +* **Scrap Salvage Techniques** - Certified by Rusted Blade Institute (2045) +* **Toxic Material Handling** - Level 2 Certification, Wasteland Hazard Compliance Board (2046) +* **Conflict Management** - Advanced Strategies for Bot-Scavenger Conflict Mitigation (2048) \ No newline at end of file diff --git a/examples/text/resume_bot.txt b/examples/text/resume_bot.txt new file mode 100644 index 0000000..1b35f88 --- /dev/null +++ b/examples/text/resume_bot.txt @@ -0,0 +1,57 @@ +Bobby Bot 3000 +Model: BB3K-47 | Powered by: Solar & the Tears of Old Batteries +Contact: bobby.bot@liferepair.net | Frequency: 204.8 MHz + +Objective: +Seeking roles that highlight my unique combination of resilience, comic timing, and ability to roll through dust storms with style. Experienced in "background comedic relief" in high-stakes, low-life environments. Ready to bring laughter and lighthearted beeps to the wasteland. + +Experience: + +Background Actor (Comic Relief), *Life Hunter* Short Film +Aug 2023 - Sept 2023 +- Provided crucial "beep boops" and comedic mechanical failures in scenes of high tension. +- Executed flawless pratfalls on cue, despite minor hardware damage, to lighten the grim tone of the post-apocalyptic landscape. +- Became an unexpected fan favorite, leading to an increase in viewer ratings by approximately 0.03%. +- Supported lead character, Jay Axel, in a climactic scene by “accidentally” showing a map with life markers upside down. + +Desert Scout Bot, Scavenger’s Union +Jan 2022 - July 2023 +- Scanned for potential life forms (or anything vaguely plant-like) across miles of barren terrain while occasionally “breaking down” to avoid high-pressure tasks. +- Maintained a perfect record of harmless self-detonations, causing minimal injury to crew morale. +- Developed a reputation for “Bobby's Famous Quotes,” including the iconic, “Life? Here? I’d sooner find a working hoverboard.” +- Led training sessions for new bots on the art of “powering down dramatically” to avoid danger. + +Self-Appointed DJ & Comedian, Scrap Heap Oasis +Oct 2021 - Dec 2021 +- Regularly performed at the Scrap Heap’s “Thursday Night Comedy Circuit” for an audience of disgruntled robots and a few confused birds. +- Known for routines such as “You Know You’re a Rusty Bot When…” and “If Circuit Boards Could Talk…” +- Played nostalgic tunes from 21st-century pop stars and pre-apocalyptic hits to keep spirits high. + +Education: + +Data Patch – Comedy & Improvisation Module, installed by unknown human +Oct 2020 +- Developed a knack for comedic timing and the ability to deliver one-liners even in the absence of a traditional sense of humor. +- Certified in “Circuit Malfunctions for Laughs” and “Expressive Servo Movement.” + +Skills: + +- **Comedic Timing:** Mastery of awkward pauses, clunky movement, and unexpected shutdowns that get laughs every time. +- **Remote Signal Mimicry:** Can replicate over 18 different distress signals and 4 types of emergency beeps. +- **Misdirection:** Trained to gesture confidently at maps, only for everyone to realize they’re upside down. +- **Technical “Expertise”:** Can diagnose 5 out of 20 mechanical issues and claim “it’s fine” for the rest. + +Film Highlights: + +- **Signature Scene:** Rolling down a hill “by accident” to provide a crucial distraction during a tense negotiation scene. +- **Popular Line:** “Oops, I seem to have misplaced my circuits… again,” followed by malfunction noises. +- **Easter Egg Moment:** Seen in the background making shadow puppets on a wall while the heroes argue about survival. + +Hobbies: + +- **Rust Removal:** Self-maintenance in downtime, often making a game of finding the shiniest bolt on my chassis. +- **Vintage Signal Collecting:** Intercepts and archives old human radio signals, with a personal best for longest uninterrupted “Jazz Hour.” +- **Comedy Writing:** Scripted over 50 jokes involving oil leaks, loose screws, and outdated hardware (available upon request). + +References: +Available from director Jay Axel, who described my performance as “surprisingly necessary,” and co-star Rusty Bot 42, who insists I’m the funniest bot they’ve ever powered down next to. diff --git a/examples/text/resume_chloe.txt b/examples/text/resume_chloe.txt new file mode 100644 index 0000000..087ed53 --- /dev/null +++ b/examples/text/resume_chloe.txt @@ -0,0 +1,55 @@ +Chloe Martinez +Email: chloem@designspace.com | (321) 654-9870 +Portfolio: www.chloemartinezdesigns.com | LinkedIn: @chloe-creative + +Objective: +Multifaceted Designer with a knack for transforming chaotic ideas into cohesive visuals. Seeking a Senior Design role where I can blend strategic design thinking with my love for vibrant, accessible, and inclusive design. + +Experience: + +Creative Director, BrightBeam Studio +Jan 2020 - Present +- Led a team of five designers to execute campaigns for tech and lifestyle brands, increasing engagement by 40%. +- Pioneered a company-wide “Design for Everyone” initiative that set new accessibility standards, making designs inclusive for all users. +- Developed a color-blind-friendly design guide, used across the company’s key projects, resulting in an 18% increase in usability for colorblind users. + +Graphic Designer, Urban Vision Inc. +Aug 2017 - Dec 2019 +- Designed marketing materials for over 20 clients in the nonprofit and social impact sectors. +- Collaborated with a team of designers and developers to create a design system that increased project efficiency by 30%. +- Specialized in infographics and data visualizations to communicate complex information in a way that was both engaging and accessible. + +Freelance Designer +May 2015 - July 2017 +- Worked with clients ranging from startup founders to local coffee shops, turning visions into logos, websites, and print materials. +- Built an interactive portfolio site from scratch (with some late-night coding and plenty of coffee). +- Awarded “Best Freelancer” by a client for outstanding service, design quality, and delivery time. + +Education: + +B.F.A. in Graphic Design, School of Visual Arts +2015 +- Thesis: “Designing for Humanity” – a project focused on creating inclusive design systems. +- Won “Most Likely to Run Out of Adobe Subscription Free Trials.” + +Skills: + +- **Design Tools:** Adobe Creative Suite (Photoshop, Illustrator, InDesign), Sketch, Figma, Canva, and, yes, even MS Paint. +- **Front-End Development:** HTML, CSS, basic JavaScript (enough to understand the devs when they talk “techie”). +- **Project Management:** Trello, Slack, and Google Suite. Known to keep projects on track even during Mercury retrograde. +- **Languages:** Bilingual in English and Spanish; basic proficiency in ASL. + +Notable Projects: + +- **RainbowPath:** Designed branding for a mental health nonprofit, creating a warm and welcoming visual identity that resonated with clients and donors alike. +- **EcoApparel Brand Launch:** Developed a social media strategy and visual assets for an eco-friendly clothing line, leading to a 200% increase in their online following. +- **Inclusive Design Workshops:** Conducted workshops on accessibility and design for nonprofits, teaching teams how to make their digital content accessible to diverse audiences. + +Hobbies: + +- **Community Mural Painting:** Collaborated on 6+ murals across the city, each telling a story about the local culture. +- **Baking & Food Photography:** Known for using design skills to make baked goods look as good as they taste. +- **Dancing Salsa and Bachata:** Enthusiastic dancer, believes in bringing movement and energy to both dance floors and design. + +References: +Available upon request – my clients will vouch for my design skills, and my mom will tell you I’m a great listener. \ No newline at end of file diff --git a/examples/text/resume_johndoe.txt b/examples/text/resume_johndoe.txt new file mode 100644 index 0000000..818feaf --- /dev/null +++ b/examples/text/resume_johndoe.txt @@ -0,0 +1,57 @@ +John "The Code Whisperer" Doe +123 Main St, Anytown, USA +johndoe@email.com | (123) 456-7890 | LinkedIn: @john-doe-incredible + +Objective: +Seeking an over-caffeinated position as a Senior Software Engineer where I can write astonishingly good code, break things occasionally, and push the boundaries of what's possible (and sometimes what's sensible). + +Experience: + +Software Engineer Extraordinaire, Tech Corp Inc. +May 2021 - Present +- Developed applications in Python that solved problems no one even knew existed. +- Single-handedly reduced load times by 73% (approximately 1 millionth of a second faster!). +- Earned "Bug Whisperer" title for solving an issue that had been plaguing the team since 2018. It was a semicolon. +- Trained 5 interns on the fine art of refactoring code while making them laugh (very important in team morale). + +Junior Code Monkey, Web Solutions LLC +July 2020 - April 2021 +- Assisted with the development of 32.5 websites. That .5 was for a client who couldn’t decide on anything. +- Debugged CSS issues so terrifying, the rest of the team refused to go near them. +- Contributed to weekly "Coding Horror Stories" sessions where my CSS exploits were often featured. + +Intern, Always Broken Enterprises +June 2019 - June 2020 +- Maintained 99.9% uptime by restarting the server daily. +- Created a sophisticated bot named *Botty McBotface* for Slack that only crashed on Fridays. +- Learned that “bug-free code” is an oxymoron, but my coffee addiction is not. + +Education: + +B.S. in Computer Science, University of Somewhere +May 2020 +- Minored in “Hitting F5 to Debug.” +- GPA: 3.1415 (approximation, just like the pie). +- Senior project: Developed a mobile app that detects sarcasm in text. Results were… mixed. + +Skills: + +- **Programming Languages:** Fluent in Python, C++, and Sarcasm. +- **Web Development:** HTML, CSS, JavaScript, and the ancient dark art of jQuery. +- **Teamwork:** Known for coordinating with others by extensive use of memes and GIFs. +- **Leadership:** Managed a rogue team of coffee-charged developers for six hours during a hackathon. + +Projects: + +- **WeatherAppButFancy:** A weather app that gives you your forecast, in haiku form. +- **Slackbot 5000:** Custom bot for work to remind people to file their TPS reports and occasionally offer words of wisdom. +- **Bug Detector 3000:** Used machine learning (and a lot of guesswork) to predict the occurrence of bugs before they even happened. Success rate: 20% (but it was funny when it worked). + +Hobbies: + +- **Competitive Refactoring:** There’s no spaghetti code I can’t untangle (or turn into worse spaghetti). +- **GIF Curation:** Handpicks the perfect GIF for any occasion, especially debugging sessions. +- **Coffee Enthusiast:** Connoisseur of fine coffee and frequent contributor to the "I need coffee" Slack channel. + +References: +Available upon request, but they’ll probably tell you the same stories. diff --git a/examples/text/resume_mario.txt b/examples/text/resume_mario.txt new file mode 100644 index 0000000..bd5bb79 --- /dev/null +++ b/examples/text/resume_mario.txt @@ -0,0 +1,56 @@ +Mario Gelato +Email: mario.gelato@frozenfun.com | (987) 123-4567 +Instagram: @mario_scoops | LinkedIn: @mario-gelato + +Objective: +Passionate Ice Cream Artisan with over a decade of experience in crafting unique, mouth-watering flavors. Seeking a role as Head Ice Cream Innovator where I can push the boundaries of frozen desserts and make the world a little sweeter, one scoop at a time. + +Experience: + +Chief Flavor Architect, The Sweetery +June 2018 - Present +- Created over 100 original flavors, including the fan favorites “Rosemary Caramel Crunch” and “Toasted Marshmallow Surprise.” +- Introduced a seasonal “Mystery Flavor” campaign that boosted social media engagement by 60%. +- Collaborated with local farmers to source fresh ingredients, leading to a 30% increase in customer loyalty for our farm-to-cone initiative. + +Ice Cream Sculptor, Dreamy Scoops Ice Cream Parlor +May 2014 - May 2018 +- Developed intricate ice cream sculptures for events, including a life-sized “Frozen Castle” that went viral. +- Trained staff on advanced scooping techniques for optimal presentation and, of course, maximum scoop satisfaction. +- Invented “The Quadruple Swirl,” a technique for adding four flavors in a single scoop – a revolutionary experience in every bite. + +Freelance Ice Cream Consultant +Jan 2011 - April 2014 +- Worked with small ice cream shops to revamp their menus, create new seasonal flavors, and train staff on advanced ice cream techniques. +- Conducted workshops on “The Art of Scooping” and “Flavor Pairing 101” to educate new artisans on the magic of balancing flavors and textures. +- Helped clients increase revenue by an average of 20% by rebranding their menus and adding Instagram-worthy treats. + +Education: + +Certificate in Dessert Innovation, Culinary Institute of the Frozen Arts +2010 +- Specialized in flavor development, dessert plating, and frozen treat chemistry. +- Senior project: “Beyond Vanilla: An Exploration of Unusual Ice Cream Flavors,” featuring Avocado Pistachio and Wasabi Mint. + +Skills: + +- **Flavor Development:** Expert in combining unconventional flavors (yes, I once made Blue Cheese Honey ice cream – surprisingly popular!). +- **Scooping Techniques:** Certified in Single Scoop Symmetry, Double Scoop Dynamics, and Triple Tower stacking. +- **Customer Engagement:** Skilled in creating memorable experiences through inventive treats and fun customer interactions. +- **Social Media:** Known for building online followings through irresistible ice cream photos and flavor reveal campaigns. + +Signature Flavors: + +- **Espresso Cardamom Crunch:** Bold espresso balanced with spicy cardamom and crunchy caramel bits. +- **Lavender Honey Lemon:** A delicate floral base with a sweet honey swirl and lemon zest – summer in a cone. +- **PB & Pickles:** Peanut butter ice cream with pickle ribbon – a controversial hit. +- **Matcha Berry Swirl:** Smooth matcha ice cream with a bold swirl of raspberry for a color-popping scoop. + +Hobbies: + +- **Food Photography:** Known for creating drool-worthy shots that capture the essence of each flavor. +- **Culinary Travel:** Travels to cities with unique ice cream scenes for “research” (and to taste all the best scoops). +- **Ice Cream History Buff:** Fascinated by the evolution of frozen desserts from ancient Rome to modern-day gelato. + +References: +Available upon request – my customers say my ice cream is life-changing, and my friends say my scoop-to-cone ratio is the best in town. diff --git a/examples/text/robot_drone_parts.csv b/examples/text/robot_drone_parts.csv new file mode 100644 index 0000000..5501ef2 --- /dev/null +++ b/examples/text/robot_drone_parts.csv @@ -0,0 +1,37 @@ +Category,Part Name,Description,Price,Stock Quantity +Propulsion,Quad Motor Set,"High-power electric motors for lift and maneuvering",250,100 +Propulsion,Extraterrestrial Gravity Coil,"Reverse-engineered coil for anti-gravity boost",5000,2 +Propulsion,Carbon Fiber Propeller,"Lightweight, durable propeller blades",30,200 +Propulsion,Ion Thruster,"For short bursts of incredible speed; requires rare fuel",800,5 +Control,Main Processor,"High-speed processor for central control",400,50 +Control,Quantum CPU,"Experimental CPU for near-instantaneous calculations",3500,3 +Control,Flight Controller Board,"Controls flight paths and stability",150,80 +Control,Earthbound Signal Amplifier,"Increases range for earth-based signals",75,120 +Control,Alien Signal Amplifier,"Boosts range for intergalactic transmissions",2500,1 +Power,Lithium-Ion Battery Pack,"Standard power source, 3 hours of flight",120,150 +Power,Plasma Battery Pack,"Advanced energy source from exoplanet mines, 24 hours of flight",4500,3 +Power,Solar Charging Panel,"Recharges battery using sunlight",60,100 +Power,Neutron Fusion Cell,"Fusion-based power source for near-limitless energy",8000,1 +Structure,Titanium Frame,"Lightweight, high-strength frame for drone body",300,40 +Structure,Reinforced Carbon Frame,"Extra durable frame for high-speed impact resistance",450,30 +Structure,Extraterrestrial Alloy Plating,"Ultra-light, self-repairing metal alloy",5000,5 +Navigation,Earth GPS Module,"Standard GPS tracking for terrestrial flights",50,200 +Navigation,Galactic Positioning Module,"Interstellar positioning for extraterrestrial navigation",6000,2 +Navigation,LIDAR Sensor,"Real-time 3D mapping and obstacle detection",300,25 +Navigation,Alien Optics Array,"Multi-spectrum sensor array for enhanced visibility",5000,4 +Sensors,Infrared Camera,"Thermal imaging for low-light navigation",150,75 +Sensors,Electromagnetic Field Detector,"Detects electromagnetic disturbances",200,40 +Sensors,Quantum Particle Analyzer,"Detects rare particles in the surrounding area",4000,1 +Sensors,Earth Soil Sampler,"Collects and analyzes earth soil samples",100,60 +Sensors,Exoplanet Soil Sampler,"Collects samples from alien environments",2500,2 +Communications,Standard Radio Transmitter,"For basic communication range",80,150 +Communications,Subspace Communicator,"Allows communication across light-years",7000,1 +Communications,Signal Jammer,"Blocks unwanted signals within a 1km radius",350,25 +Defense,Anti-Laser Shield,"Deflects low-power lasers",500,20 +Defense,Plasma Shield,"Protects against high-energy plasma blasts",7500,2 +Defense,Electromagnetic Pulse (EMP) Disruptor,"Disables nearby electronics for 5 seconds",1500,8 +Defense,Extraterrestrial Force Field Emitter,"Generates an energy field, immune to known weapons",10000,1 +Extras,Self-Healing Nanobots,"Automated repair bots for minor structural damage",2000,5 +Extras,Atmospheric Stabilizer,"Enables stable flight in thin atmospheres",1000,10 +Extras,Holographic Cloaking Device,"Renders drone invisible to standard detection",9000,1 +Extras,Alien Language Translator,"For decoding extraterrestrial languages",3000,2 diff --git a/examples/text/sales_forecast.csv b/examples/text/sales_forecast.csv new file mode 100644 index 0000000..082dcf2 --- /dev/null +++ b/examples/text/sales_forecast.csv @@ -0,0 +1,25 @@ +Month,Product,Expected Sales,Season +January,Winter Jacket,150,Winter +January,Snow Boots,100,Winter +February,Winter Jacket,130,Winter +February,Snow Boots,90,Winter +March,Spring Jacket,100,Spring +March,Raincoat,150,Spring +April,Spring Jacket,200,Spring +April,Raincoat,250,Spring +May,Summer T-shirt,300,Summer +May,Shorts,220,Summer +June,Summer T-shirt,500,Summer +June,Shorts,450,Summer +July,Summer T-shirt,600,Summer +July,Shorts,550,Summer +August,Summer T-shirt,550,Summer +August,Shorts,500,Summer +September,Fall Sweater,250,Fall +September,Jeans,200,Fall +October,Fall Sweater,300,Fall +October,Jeans,350,Fall +November,Winter Jacket,400,Winter +November,Snow Boots,320,Winter +December,Winter Jacket,450,Winter +December,Snow Boots,370,Winter diff --git a/js/ExtractionNodes.js b/js/ExtractionNodes.js index ef9bcc3..05de454 100644 --- a/js/ExtractionNodes.js +++ b/js/ExtractionNodes.js @@ -4,7 +4,8 @@ import { formatAndDisplayJSON } from "./gtUIUtils.js"; import { hideWidget, showWidget } from "./utils.js"; import { app } from "../../../scripts/app.js"; export function setupExtractionNodes(nodeType, nodeData, app) { - if (nodeData.name === "Griptape Tool: Extraction") { + if (nodeData.name.includes("Extraction")) + { setupExtractionTypeAttrr(nodeType, nodeData, app); } } diff --git a/js/NodesWithVisibilityToggles.js b/js/NodesWithVisibilityToggles.js new file mode 100644 index 0000000..dd776d3 --- /dev/null +++ b/js/NodesWithVisibilityToggles.js @@ -0,0 +1,100 @@ +import { ComfyWidgets } from "../../../scripts/widgets.js"; +import { fitHeight } from "./utils.js"; +import { formatAndDisplayJSON } from "./gtUIUtils.js"; +import { hideWidget, showWidget } from "./utils.js"; +import { app } from "../../../scripts/app.js"; +export function setupVisibilityToggles(nodeType, nodeData, app) { + if (nodeData.name.includes("Black Forest Labs Image Generation")) { + setupBlackForestLabsImageGenerationNode(nodeType, nodeData, app); + } +} + +function setupBlackForestLabsImageGenerationNode(nodeType, nodeData, app) { + const onNodeCreated = nodeType.prototype.onNodeCreated; + nodeType.prototype.onNodeCreated = function () { + const me = onNodeCreated?.apply(this); + const widget_model = this.widgets.find( + (w) => w.name === "image_generation_model" + ); + + const width_widget = this.widgets.find((w) => w.name === "width"); + const height_widget = this.widgets.find((w) => w.name === "height"); + const aspect_ratio_width_widget = this.widgets.find( + (w) => w.name === "aspect_ratio_width" + ); + const aspect_ratio_height_widget = this.widgets.find( + (w) => w.name === "aspect_ratio_height" + ); + + const raw_widget = this.widgets.find((w) => w.name === "raw"); + const guidance_widget = this.widgets.find((w) => w.name === "guidance"); + const steps_widget = this.widgets.find((w) => w.name === "steps"); + const interval_widget = this.widgets.find((w) => w.name === "interval"); + const prompt_upsampling_widget = this.widgets.find( + (w) => w.name === "prompt_upsampling" + ); + const image_prompt_strength_widget = this.widgets.find((w) => w.name === "image_prompt_strength"); + + // Hide both widgets + widget_model.callback = async () => { + hideWidget(this, width_widget); + hideWidget(this, height_widget); + hideWidget(this, aspect_ratio_width_widget); + hideWidget(this, aspect_ratio_height_widget); + hideWidget(this, raw_widget); + hideWidget(this, guidance_widget); + hideWidget(this, steps_widget); + hideWidget(this, interval_widget); + hideWidget(this, prompt_upsampling_widget); + hideWidget(this, image_prompt_strength_widget); + + switch (widget_model.value) { + case "flux-pro-1.1-ultra": + showWidget(aspect_ratio_height_widget); + showWidget(aspect_ratio_width_widget); + showWidget(raw_widget); + showWidget(image_prompt_strength_widget); + break; + case "flux-pro-1.1": + showWidget(width_widget); + showWidget(height_widget); + showWidget(prompt_upsampling_widget); + break; + case "flux-pro": + showWidget(width_widget); + showWidget(height_widget); + showWidget(prompt_upsampling_widget); + showWidget(interval_widget); + showWidget(guidance_widget); + showWidget(steps_widget); + break; + case "flux-dev": + showWidget(width_widget); + showWidget(height_widget); + showWidget(guidance_widget); + showWidget(steps_widget); + showWidget(prompt_upsampling_widget); + break; + case "flux-pro-1.0-depth": + case "flux-pro-1.0-canny": + showWidget(guidance_widget); + showWidget(steps_widget); + showWidget(prompt_upsampling_widget); + break; + case "flux-pro-1.0-fill": + showWidget(guidance_widget); + showWidget(steps_widget); + showWidget(prompt_upsampling_widget); + break; + default: + break; + } + fitHeight(this, true); + }; + + setTimeout(() => { + widget_model.callback(); + }, 5); + return me; + }; +} diff --git a/js/TextLoaderModuleNodes.js b/js/TextLoaderModuleNodes.js index caf23e4..14fa368 100644 --- a/js/TextLoaderModuleNodes.js +++ b/js/TextLoaderModuleNodes.js @@ -11,20 +11,53 @@ export function setupTextLoaderModuleNodes(nodeType, nodeData, app) { const me = onNodeCreated?.apply(this); const widget_loader_type = this.widgets.find(w => w.name === 'loader'); const widget_text = this.widgets.find(w=> w.name === 'text'); + const file_path = this.widgets.find(w=> w.name === 'file_path'); const widget_url = this.widgets.find(w=> w.name === 'url'); + const upload_button = this.widgets.find(w=> w.name === 'choose text to upload'); + const input_source = this.widgets.find(w=> w.name === 'input_source'); - // Hide both widgets + // Hide widgets widget_loader_type.callback = async() => { hideWidget(this, widget_url); - + hideWidget(this, input_source); switch (widget_loader_type.value) { case "WebLoader": showWidget(widget_url); break; + case "TextLoader": + showWidget(input_source); + break; + case "CsvLoader": + showWidget(input_source); + break; + case "PdfLoader": + input_source.value = "File Path"; + showWidget(input_source); + showWidget(file_path); + showWidget(upload_button); + break; } } + input_source.callback = async() => { + hideWidget(this, file_path); + hideWidget(this, upload_button); + if (input_source.value == "File Path") { + showWidget(file_path); + showWidget(upload_button); + } + else { + hideWidget(this, file_path); + hideWidget(this, upload_button); + } + + } - setTimeout(() => { widget_loader_type.callback() }, 5); + setTimeout(() => { + input_source.callback(); + }, 5); + setTimeout(() => { + widget_loader_type.callback(); + }, 5); return me; // setupMessageStyle(this.message); }; diff --git a/js/griptape_api_keys.js b/js/griptape_api_keys.js index bad3ee1..39402ce 100644 --- a/js/griptape_api_keys.js +++ b/js/griptape_api_keys.js @@ -1,54 +1,28 @@ export const keys_organized = { - "@Griptape": [ - "GRIPTAPE_CLOUD_API_KEY" - ], - "OpenAI": [ - "OPENAI_API_KEY" - ], - "Amazon": [ - "AWS_ACCESS_KEY_ID", - "AWS_SECRET_ACCESS_KEY", - "AWS_DEFAULT_REGION", - "AMAZON_OPENSEARCH_HOST", - "AMAZON_OPENSEARCH_INDEX_NAME" - ], - "Anthropic": [ - "ANTHROPIC_API_KEY" - ], - "Microsoft Azure": [ - "AZURE_OPENAI_ENDPOINT", - "AZURE_OPENAI_DALL_E_3_ENDPOINT", - "AZURE_OPENAI_DALL_E_3_API_KEY", - "AZURE_OPENAI_API_KEY" - ], - "Cohere": [ - "COHERE_API_KEY" - ], - "Eleven Labs": [ - "ELEVEN_LABS_API_KEY" - ], - "Exa": [ - "EXA_API_KEY" - ], - "Groq": [ - "GROQ_API_KEY" - ], - "Google": [ - "GOOGLE_API_KEY", - "GOOGLE_API_SEARCH_ID" - ], - "Huggingface": [ - "HUGGINGFACE_HUB_ACCESS_TOKEN" - ], - "LeonardoAI": [ - "LEONARDO_API_KEY" - ], - "Pinecone": [ - "PINECONE_API_KEY", - "PINECONE_ENVIRONMENT", - "PINECONE_INDEX_NAME" - ], - "Tavily": [ - "TAVILY_API_KEY" - ] - } \ No newline at end of file + "@Griptape": ["GRIPTAPE_CLOUD_API_KEY"], + OpenAI: ["OPENAI_API_KEY"], + Amazon: [ + "AWS_ACCESS_KEY_ID", + "AWS_SECRET_ACCESS_KEY", + "AWS_DEFAULT_REGION", + "AMAZON_OPENSEARCH_HOST", + "AMAZON_OPENSEARCH_INDEX_NAME", + ], + Anthropic: ["ANTHROPIC_API_KEY"], + "BlackForest Labs": ["BFL_API_KEY"], + "Microsoft Azure": [ + "AZURE_OPENAI_ENDPOINT", + "AZURE_OPENAI_DALL_E_3_ENDPOINT", + "AZURE_OPENAI_DALL_E_3_API_KEY", + "AZURE_OPENAI_API_KEY", + ], + Cohere: ["COHERE_API_KEY"], + "Eleven Labs": ["ELEVEN_LABS_API_KEY"], + Exa: ["EXA_API_KEY"], + Groq: ["GROQ_API_KEY"], + Google: ["GOOGLE_API_KEY", "GOOGLE_API_SEARCH_ID"], + Huggingface: ["HUGGINGFACE_HUB_ACCESS_TOKEN"], + LeonardoAI: ["LEONARDO_API_KEY"], + Pinecone: ["PINECONE_API_KEY", "PINECONE_ENVIRONMENT", "PINECONE_INDEX_NAME"], + Tavily: ["TAVILY_API_KEY"], +}; diff --git a/js/gtUIMenuSeparator.js b/js/gtUIMenuSeparator.js index 76d0d77..7295505 100644 --- a/js/gtUIMenuSeparator.js +++ b/js/gtUIMenuSeparator.js @@ -1,43 +1,43 @@ // Menu items that should have a separator above them const sep_above_items = [ - // Main Menu Items - "Agent Configs", - "Display", - "Audio", - // Sub Menu Items - Agent - "Griptape Run: Agent", - "Griptape Expand: Agent Nodes", - "Griptape Convert: Agent to Tool", - // Sub Menu Item - Agent Configs - "Griptape Agent Config: Amazon Bedrock Drivers", - // Sub Menu Item - Agent Tools - "Griptape Tool: Audio Transcription", - "Griptape Tool: Extraction", - // Sub Menu Item - Audio - "Griptape Load: Audio", - // Sub Menu Items - Image - "Griptape Load: Image From URL", - "Griptape Run: Image Description", - // Sub Menu Items - Text - "Griptape Convert: Text to CLIP Encode", - "Griptape Combine: Merge Texts", - "Griptape Load: Text", - "Griptape Vector Store: Add Text", - // Sub Menu Items - RAG - "Griptape RAG Query: Translate Module", - "Griptape RAG Retrieve: Text Loader Module", - "Griptape RAG Rerank: Text Chunks Module", - "Griptape RAG Response: Prompt Module", - -] + // Main Menu Items + "Agent Configs", + "Display", + "Audio", + // Sub Menu Items - Agent + "Griptape Run: Agent", + "Griptape Expand: Agent Nodes", + "Griptape Convert: Agent to Tool", + // Sub Menu Item - Agent Configs + "Griptape Agent Config: Amazon Bedrock Drivers", + // Sub Menu Item - Agent Tools + "Griptape Tool: Audio Transcription", + "Griptape Tool: Extraction", + // Sub Menu Item - Audio + "Griptape Load: Audio", + // Sub Menu Items - Image + "Griptape Load: Image From URL", + "Griptape Run: Image Description", + // Sub Menu Items - Text + "Griptape Convert: Text to CLIP Encode", + "Griptape Combine: Merge Texts", + "Griptape Load: Text", + "Griptape Vector Store: Add Text", + "Griptape Run: Text Extraction", + // Sub Menu Items - RAG + "Griptape RAG Query: Translate Module", + "Griptape RAG Retrieve: Text Loader Module", + "Griptape RAG Rerank: Text Chunks Module", + "Griptape RAG Response: Prompt Module", +]; export function setupMenuSeparator() { - const originalAddItem = LiteGraph.ContextMenu.prototype.addItem; - LiteGraph.ContextMenu.prototype.addItem = function (name, value, options) { - for (let item of sep_above_items) { - if (name === item) { - this.addItem("", null) - } + const originalAddItem = LiteGraph.ContextMenu.prototype.addItem; + LiteGraph.ContextMenu.prototype.addItem = function (name, value, options) { + for (let item of sep_above_items) { + if (name === item) { + this.addItem("", null); } - return originalAddItem.apply(this, arguments); } -} \ No newline at end of file + return originalAddItem.apply(this, arguments); + }; +} diff --git a/js/gtUINodes.js b/js/gtUINodes.js index dfb363b..0bf2f10 100644 --- a/js/gtUINodes.js +++ b/js/gtUINodes.js @@ -8,9 +8,9 @@ import { setupCombineNodes } from "./CombineNodes.js"; import { setupExtractionNodes } from "./ExtractionNodes.js"; import { setupTextLoaderModuleNodes } from "./TextLoaderModuleNodes.js"; import { gtUIAddUploadWidget } from "./gtUIUtils.js"; -import { setupMenuSeparator } from "./gtUIMenuSeparator.js"; +import { setupMenuSeparator } from "./gtUIMenuSeparator.js"; import { keys_organized } from "./griptape_api_keys.js"; - +import { setupVisibilityToggles } from "./NodesWithVisibilityToggles.js"; app.registerExtension({ name: "comfy.gtUI", beforeConfigureGraph: (graphData, missingNodeTypes) => { @@ -21,7 +21,6 @@ app.registerExtension({ } }, setup: (app) => { - setupMenuSeparator(); function messageHandler(event) { // console.log(event.detail.message) @@ -30,41 +29,41 @@ app.registerExtension({ // Create the settings Object.entries(keys_organized).forEach(([category, keys]) => { - keys.forEach(key => { - app.ui.settings.addSetting({ - id: `Griptape.${key}`, - category: ["Griptape", category, key], - name: key, - type: "text", - defaultValue: "", - /* To listen for changes, add an onChange parameter + keys.forEach((key) => { + app.ui.settings.addSetting({ + id: `Griptape.${key}`, + category: ["Griptape", category, key], + name: key, + type: "text", + defaultValue: "", + /* To listen for changes, add an onChange parameter onChange: (newVal, oldVal) => { console.log("Setting got changed!") }, */ - }); + }); }); }); }, - - init() { - - }, + init() {}, async beforeRegisterNodeDef(nodeType, nodeData, app) { setupNodeColors(nodeType, nodeData, app); setupConfigurationNodes(nodeType, nodeData, app); setupDisplayNodes(nodeType, nodeData, app); setupCombineNodes(nodeType, nodeData, app); setupExtractionNodes(nodeType, nodeData, app); - setupTextLoaderModuleNodes(nodeType, nodeData, app); + setupVisibilityToggles(nodeType, nodeData, app); - // Create Audio Node if (nodeData.name === "Griptape Load: Audio") { - gtUIAddUploadWidget(nodeType, nodeData, "audio", "audio") + gtUIAddUploadWidget(nodeType, nodeData, "audio", "audio"); } // Load Text Node if (nodeData.name === "Griptape Load: Text") { - gtUIAddUploadWidget(nodeType, nodeData, "text", "text") + gtUIAddUploadWidget(nodeType, nodeData, "text", "text"); + } + if (nodeData.name === "Griptape RAG Retrieve: Text Loader Module") { + gtUIAddUploadWidget(nodeType, nodeData, "file_path", "text"); } - } + setupTextLoaderModuleNodes(nodeType, nodeData, app); + }, }); diff --git a/js/gtUIUtils.js b/js/gtUIUtils.js index 42a077b..314584d 100644 --- a/js/gtUIUtils.js +++ b/js/gtUIUtils.js @@ -168,7 +168,7 @@ export function gtUIAddUploadWidget(nodeType, nodeData, widgetName, type="audio" console.log("text here") Object.assign(fileInput, { type: "file", - accept: "text/plain,text/markdown,text/html,text/csv,text/xml,text/yaml,text/json", + accept: "text/plain,text/markdown,text/html,text/csv,text/xml,text/yaml,text/json,application/json,application/pdf,application/x-yaml,application/vnd.ms-excel,application/csv,application/tsv,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,text/tab-separated-values,text/info", style: "display: none", onchange: async () => { if (fileInput.files.length) { diff --git a/js/nodeFixes.js b/js/nodeFixes.js index 5109eb6..c4c0294 100644 --- a/js/nodeFixes.js +++ b/js/nodeFixes.js @@ -19,9 +19,12 @@ export const nodeFixes = { "gtUIOutputArtifactNode": "Griptape Display: Artifact", "ImageQueryTask": "Griptape Run: Image Description", "ParallelImageQueryTask": "Griptape Run: Parallel Image Description", - "PromptTask": "Griptape Run: Prompt Task", - "ToolTask": "Griptape Run: Tool Task", - "ToolkitTask": "Griptape Run: Toolkit Task", + "PromptTask": "Griptape Run: Task", + "ToolTask": "Griptape Run: Task", + "ToolkitTask": "Griptape Run: Task", + "Griptape Run: Prompt Task": "Griptape Run: Task", + "Griptape Run: Tool Task": "Griptape Run: Task", + "Griptape Run: Toolkit Task": "Griptape Run: Task", "TextSummaryTask": "Griptape Run: Text Summary", "AudioTranscriptionTask": "Griptape Run: Audio Transcription", "ExpandAgent": "Griptape Expand: Agent Nodes", diff --git a/js/versions.js b/js/versions.js index 51a2a35..f474bad 100644 --- a/js/versions.js +++ b/js/versions.js @@ -1,170 +1,136 @@ export const versions = { - "version": "0.34.2", - "releaseDate": "2024-11-9", - "name": "ComfyUI-Griptape", - "description": "Griptape integration for ComfyUI", - "author": "Jason Schleifer", - "repository": "https://github.com/griptape-ai/ComfyUI-Griptape", - "changelog": [ - { - "version": "0.34.2", - "date": "2024-11-6", - "changes": [ - "Fixed issue with `dynamicprompt` inputs", - ] - }, - { - "version": "0.34.1", - "date": "2024-11-6", - "changes": [ - "Fixed issue with `dynamicprompt` inputs", - ] - }, - { - "version": "0.34.0g", - "date": "2024-11-5", - "changes": [ - "Fixed issue with `dynamicprompt` inputs", - ] - }, - { - "version": "0.34.0f", - "date": "2024-11-4", - "changes": [ - "Fixed install issue", - ] - }, - { - "version": "0.34.0e", - "date": "2024-11-1", - "changes": [ - "Fixed base agent", - ] - }, - { - "version": "0.34.0d", - "date": "2024-11-1", - "changes": [ - "fixed import of eleven labs api key", - ] - }, - { - "version": "0.34.0c", - "date": "2024-11-1", - "changes": [ - "Updated environment configuration", - ] - }, - { - "version": "0.34.0b", - "date": "2024-10-31", - "changes": [ - "fix convert agent to tool node", - ] - }, - { - "version": "0.34.0a", - "date": "2024-10-31", - "changes": [ + version: "0.34.3", + releaseDate: "2024-11-9", + name: "ComfyUI-Griptape", + description: "Griptape integration for ComfyUI", + author: "Jason Schleifer", + repository: "https://github.com/griptape-ai/ComfyUI-Griptape", + changelog: [ + { + version: "0.34.3", + date: "2024-11-21", + changes: ["Updated to Griptape 0.34.3 and made a few other fixes"], + }, + { + version: "0.34.2", + date: "2024-11-6", + changes: ["Fixed issue with `dynamicprompt` inputs"], + }, + { + version: "0.34.1", + date: "2024-11-6", + changes: ["Fixed issue with `dynamicprompt` inputs"], + }, + { + version: "0.34.0g", + date: "2024-11-5", + changes: ["Fixed issue with `dynamicprompt` inputs"], + }, + { + version: "0.34.0f", + date: "2024-11-4", + changes: ["Fixed install issue"], + }, + { + version: "0.34.0e", + date: "2024-11-1", + changes: ["Fixed base agent"], + }, + { + version: "0.34.0d", + date: "2024-11-1", + changes: ["fixed import of eleven labs api key"], + }, + { + version: "0.34.0c", + date: "2024-11-1", + changes: ["Updated environment configuration"], + }, + { + version: "0.34.0b", + date: "2024-10-31", + changes: ["fix convert agent to tool node"], + }, + { + version: "0.34.0a", + date: "2024-10-31", + changes: [ "fix for ollama driver to not break if no embedding driver specified", - ] - }, - { - "version": "0.34.0", - "date": "2024-10-30", - "changes": [ - "Update to Griptape v0.34.0", - ] - }, - { - "version": "0.33.1", - "date": "2024-10-23", - "changes": [ - "Update to Griptape v0.33.1", - ] - }, - { - "version": "0.33.0", - "date": "2024-10-11", - "changes": [ - "Update to Griptape v0.33.0", - ] - }, - { - "version": "0.31.0e", - "date": "2024-09-20", - "changes": [ - "Fixed connection error for LMStudio Drivers", - ] - }, - { - "version": "0.31.0d", - "date": "2024-09-12", - "changes": [ - "Fixed Griptape Run: Tool Task node", - ] - }, - { - "version": "0.31.0c", - "date": "2024-09-11", - "changes": [ - "Fixed resizing of display text node", - ] - }, - { - "version": "0.31.0b", - "date": "2024-09-10", - "changes": [ - "Hotfix to remove icecream", - ] - }, - { - "version": "0.31.0a", - "date": "2024-09-10", - "changes": [ - "Added ability to create modelfiles for Ollama", - ] - }, - { - "version": "0.31.0", - "date": "2024-09-05", - "changes": [ + ], + }, + { + version: "0.34.0", + date: "2024-10-30", + changes: ["Update to Griptape v0.34.0"], + }, + { + version: "0.33.1", + date: "2024-10-23", + changes: ["Update to Griptape v0.33.1"], + }, + { + version: "0.33.0", + date: "2024-10-11", + changes: ["Update to Griptape v0.33.0"], + }, + { + version: "0.31.0e", + date: "2024-09-20", + changes: ["Fixed connection error for LMStudio Drivers"], + }, + { + version: "0.31.0d", + date: "2024-09-12", + changes: ["Fixed Griptape Run: Tool Task node"], + }, + { + version: "0.31.0c", + date: "2024-09-11", + changes: ["Fixed resizing of display text node"], + }, + { + version: "0.31.0b", + date: "2024-09-10", + changes: ["Hotfix to remove icecream"], + }, + { + version: "0.31.0a", + date: "2024-09-10", + changes: ["Added ability to create modelfiles for Ollama"], + }, + { + version: "0.31.0", + date: "2024-09-05", + changes: [ "Updated Griptape Framework to v0.31.0", "Added Griptape RAG Capabilities", "Added New Griptape Config Driver Nodes", "Bug fixes and improvements", - ] + ], }, { - "version": "0.30.2a", - "date": "2024-08-30", - "changes": [ + version: "0.30.2a", + date: "2024-08-30", + changes: [ "Added Griptape Tool: Extraction node", "Added Griptape Tool: Prompt Summary", "Addded max_tokens parameter to most prompt models", - ] + ], }, { - "version": "0.30.2", - "date": "2024-08-29", - "changes": [ - "New release" - ] + version: "0.30.2", + date: "2024-08-29", + changes: ["New release"], }, { - "version": "0.30.2", - "date": "2024-08-26", - "changes": [ - "New release" - ] + version: "0.30.2", + date: "2024-08-26", + changes: ["New release"], }, { - "version": "0.30.2", - "date": "2024-08-21", - "changes": [ - "Fixed querying for models in LMStudio and Ollama on import" - ] - } - ] -} - + version: "0.30.2", + date: "2024-08-21", + changes: ["Fixed querying for models in LMStudio and Ollama on import"], + }, + ], +}; diff --git a/nodes/agent/BaseAgent.py b/nodes/agent/BaseAgent.py index 195308b..cb5c11c 100644 --- a/nodes/agent/BaseAgent.py +++ b/nodes/agent/BaseAgent.py @@ -148,8 +148,8 @@ def run(self, **kwargs): tools = kwargs.get("tools", []) rulesets = kwargs.get("rulesets", []) input_string = kwargs.get("input_string", None) - print(f"STRING: {STRING=}") - print(f"input_string: {input_string=}") + # print(f"STRING: {STRING=}") + # print(f"input_string: {input_string=}") # Defaults.drivers_config = DriversConfig() create_dict = {} # Configuration diff --git a/nodes/agent/gtComfyAgent.py b/nodes/agent/gtComfyAgent.py index bd903aa..5382214 100644 --- a/nodes/agent/gtComfyAgent.py +++ b/nodes/agent/gtComfyAgent.py @@ -63,7 +63,6 @@ def model_check(self): simple_models = ["llama3", "llama3:latest", "mistral", "LLama-3"] drivers = ["OllamaPromptDriver", "LMStudioPromptDriver"] agent_prompt_driver_name = self.prompt_driver.__class__.__name__ - print(f"Agent Prompt Driver Name: {agent_prompt_driver_name=}") model = self.prompt_driver.model if agent_prompt_driver_name in drivers: if model == "": diff --git a/nodes/drivers/gtUIBlackForestImageGenerationDriver.py b/nodes/drivers/gtUIBlackForestImageGenerationDriver.py new file mode 100644 index 0000000..f6206d0 --- /dev/null +++ b/nodes/drivers/gtUIBlackForestImageGenerationDriver.py @@ -0,0 +1,237 @@ +from griptape.black_forest.drivers.black_forest_image_generation_driver import ( + BlackForestImageGenerationDriver, +) + +from .gtUIBaseImageDriver import gtUIBaseImageGenerationDriver + +DEFAULT_API_KEY = "BFL_API_KEY" +models = [ + "flux-pro-1.1", + "flux-pro-1.1-ultra", + "flux-pro", + "flux-dev", + "flux-pro-1.0-canny", + "flux-pro-1.0-depth", + "flux-pro-1.0-fill", +] +widths = [str(i) for i in range(256, 1441, 32)] +heights = [str(i) for i in range(256, 1441, 32)] +safety_tolerance_list = ["strict", "high", "medium", "low", "very_low", "none"] +aspect_ratios = [f"{w}:{h}" for w in range(21, 8, -1) for h in range(9, 22)] + + +class gtUIBlackForestImageGenerationDriver(gtUIBaseImageGenerationDriver): + DESCRIPTION = "Black Forest Image Generation Driver to use Flux models." + + @classmethod + def INPUT_TYPES(s): + inputs = super().INPUT_TYPES() + inputs["optional"].update( + { + "image_generation_model": ( + models, + { + "default": models[0], + "tooltip": "Select the image generation model.", + }, + ), + "width": ( + widths, + {"default": "1024", "tooltip": "Select the desired image width."}, + ), + "height": ( + heights, + {"default": "768", "tooltip": "Select the desired image height."}, + ), + "aspect_ratio_width": ( + "INT", + { + "default": 16, + "min": 9, + "max": 21, + "tooltip": "Select the desired aspect width.", + }, + ), + "aspect_ratio_height": ( + "INT", + { + "default": 9, + "min": 9, + "max": 21, + "tooltip": "Select the desired aspect height.", + }, + ), + "prompt_upsampling": ( + "BOOLEAN", + { + "default": False, + "tooltip": "Whether to perform upsampling on the prompt. If active, automatically modifies the prompt for more creative generation.", + "label_on": "True (Modify Prompt)", + "label_off": "False (No Modification)", + }, + ), + "safety_tolerance": ( + safety_tolerance_list, + { + "default": safety_tolerance_list[2], + "tooltip": "Select the safety tolerance level.", + }, + ), + "steps": ( + "INT", + { + "default": None, + "tooltip": "Number of steps for the image generation process. Values: 1-50", + "min": 0, + "max": 50, + }, + ), + "guidance": ( + "FLOAT", + { + "default": 0.0, + "tooltip": "Optional guidance scale for image generation. \n\nFor 'flux-dev' and 'flux-pro', values are 1.5-5. High guidance scales improve prompt adherence at the cost of reduced realism.\n\nFor 'flux-pro-1.0-canny' and 'flux-pro-1.0-depth' values are 1-100 and higher guidance applies image over prompt.", + }, + ), + "interval": ( + "INT", + { + "default": None, + "tooltip": "Optional interval parameter for guidance control. Values: 1-4", + "min": 0, + "max": 4, + }, + ), + "seed": ( + "INT", + { + "default": 10342349342, + "tooltip": "Seed for random number generation.", + }, + ), + "raw": ( + "BOOLEAN", + { + "default": False, + "tooltip": "Generate less processed, more natural-looking images", + }, + ), + "image_prompt_strength": ( + "FLOAT", + { + "default": 0.1, + "tooltip": "Image prompt strength. Values: 0.0-1.0. Higher values increase the influence of the image.", + "min": 0, + "max": 1, + }, + ), + "api_key_env_var": ( + "STRING", + { + "default": DEFAULT_API_KEY, + "tooltip": "Enter the environment variable name for the API key, not the actual API key.", + }, + ), + } + ) + + return inputs + + def build_params(self, **kwargs): + model = kwargs.get("image_generation_model", models[0]) + width = kwargs.get("width", "1024") + height = kwargs.get("height", "768") + aspect_ratio_width = kwargs.get("aspect_ratio_width", 16) + aspect_ratio_height = kwargs.get("aspect_ratio_height", 9) + aspect_ratio = f"{aspect_ratio_width}:{aspect_ratio_height}" + prompt_upsampling = kwargs.get("prompt_upsampling", False) + safety_tolerance_str = kwargs.get("safety_tolerance", safety_tolerance_list[2]) + safety_tolerance = safety_tolerance_list.index(safety_tolerance_str) + image_prompt_strength = kwargs.get("image_prompt_strength", 0.1) + seed = kwargs.get("seed", 10342349342) + steps = kwargs.get("steps", None) + guidance = kwargs.get("guidance", None) + + interval = kwargs.get("interval", 0.5) + raw = kwargs.get("raw", False) + api_key = self.getenv(kwargs.get("api_key_env_var", DEFAULT_API_KEY)) + + params = {} + + if model: + params["model"] = model + if safety_tolerance: + params["safety_tolerance"] = int(safety_tolerance) + if seed: + params["seed"] = int(seed) + if api_key: + params["api_key"] = api_key + + # Ultra model specific settings + if model == "flux-pro-1.1-ultra": + if aspect_ratio: + params["aspect_ratio"] = aspect_ratio + if raw: + params["raw"] = bool(raw) + if image_prompt_strength: + params["image_prompt_strength"] = float(image_prompt_strength) + # Fill model specific settings + if model == "flux-pro-1.0-fill": + if guidance is not None and guidance > 0: + if guidance < 1.5: + guidance == 1.5 + if guidance > 100: + raise ValueError( + f"When using {model}, guidance must be between 1.5 and 100." + ) + params["guidance"] = float(guidance) + # Canny/Depth model specific settings + if model in ["flux-pro-1.0-canny", "flux-pro-1.0-depth"]: + if guidance is not None and guidance > 0: + if guidance < 1: + guidance == 1 + params["guidance"] = float(guidance) + + # Dev/Pro specific settings + if model in ["flux-dev", "flux-pro"]: + if guidance is not None and guidance > 0: + if guidance < 1.5: + guidance == 1.5 + if guidance > 5: + raise ValueError( + f"When using {model}, guidance must be between 1.5 and 5." + ) + + params["guidance"] = float(guidance) + + # Pro model specific settings + if model == "flux-pro": + if interval is not None and interval > 0: + params["interval"] = int(interval) + + # Dev/Pro/Canny/Depth specific settings + if model in [ + "flux-dev", + "flux-pro", + "flux-pro-1.0-canny", + "flux-pro-1.0-depth", + ]: + if steps is not None and steps > 0: + params["steps"] = int(steps) + if prompt_upsampling: + params["prompt_upsampling"] = bool(prompt_upsampling) + + # Flux-pro-1.1, flux-dev, flux-pro specific settings + if model in ["flux-dev", "flux-pro", "flux-pro-1.1"]: + if width: + params["width"] = int(width) + if height: + params["height"] = int(height) + + return params + + def create(self, **kwargs): + params = self.build_params(**kwargs) + params["max_attempts"] = 1 + driver = BlackForestImageGenerationDriver(**params) + return (driver,) diff --git a/nodes/drivers/gtUIOllamaPromptDriver.py b/nodes/drivers/gtUIOllamaPromptDriver.py index b7565ad..f356adf 100644 --- a/nodes/drivers/gtUIOllamaPromptDriver.py +++ b/nodes/drivers/gtUIOllamaPromptDriver.py @@ -44,7 +44,13 @@ def INPUT_TYPES(s): # Add the base optional inputs to the inputs inputs["optional"].update(base_optional_inputs) inputs["optional"]["model"] = ((), {"tooltip": "The prompt model to use"}) - + inputs["optional"]["keep_alive"] = ( + "INT", + { + "default": 240, + "tooltip": "Seconds to keep the connection alive", + }, + ) return inputs FUNCTION = "create" @@ -57,6 +63,7 @@ def build_params(self, **kwargs): max_attempts = kwargs.get("max_attempts_on_fail", None) use_native_tools = kwargs.get("use_native_tools", False) max_tokens = kwargs.get("max_tokens", None) + keep_alive = kwargs.get("keep_alive", 240) params = { "model": model, @@ -64,11 +71,11 @@ def build_params(self, **kwargs): "max_attempts": max_attempts, "use_native_tools": use_native_tools, } - if base_url and port: params["host"] = f"{base_url}:{port}" if max_tokens > 0: params["max_tokens"] = max_tokens + params["extra_params"] = {"keep_alive": keep_alive} return params def create(self, **kwargs): diff --git a/nodes/loaders/gtUILoadText.py b/nodes/loaders/gtUILoadText.py index 2bf34ea..f01a2fd 100644 --- a/nodes/loaders/gtUILoadText.py +++ b/nodes/loaders/gtUILoadText.py @@ -1,12 +1,7 @@ -import mimetypes import os import folder_paths - - -def is_audio_file(filepath): - mime_type, _ = mimetypes.guess_type(filepath) - return mime_type is not None and mime_type.startswith("text/") +from griptape.loaders import PdfLoader, TextLoader class gtUILoadText: @@ -21,6 +16,10 @@ class gtUILoadText: ".txt", ".yaml", ".yml", + ".csv", + ".tsv", + ".md", + ".pdf", ) @classmethod @@ -34,7 +33,7 @@ def INPUT_TYPES(s): and f.endswith(gtUILoadText.SUPPORTED_FORMATS) ) ] - return {"required": {"text": (sorted(files), {"text_upload": False})}} + return {"required": {"text": (sorted(files), {"text_upload": True})}} CATEGORY = "Griptape/Text" @@ -44,10 +43,21 @@ def INPUT_TYPES(s): def gt_load_text(self, text): text_path = folder_paths.get_annotated_filepath(text) - text_data = "" - with open(text_path, "r") as f: - text_data = f.read() + # get the extension + ext = os.path.splitext(text_path)[1] + if ext == ".pdf": + text_data = PdfLoader().load(text_path)[0] + else: + text_data = TextLoader().load(text_path) + return ( text_path, - text_data, + text_data.value, ) + # text_data = "" + # with open(text_path, "r", encoding="utf-8") as f: + # text_data = f.read() + # return ( + # text_path, + # text_data, + # ) diff --git a/nodes/rag/gtUITextLoaderRetrievalRagModule.py b/nodes/rag/gtUITextLoaderRetrievalRagModule.py index 9351d2e..3d55e96 100644 --- a/nodes/rag/gtUITextLoaderRetrievalRagModule.py +++ b/nodes/rag/gtUITextLoaderRetrievalRagModule.py @@ -1,11 +1,14 @@ +import os import tempfile +import folder_paths from griptape.engines.rag.modules import TextLoaderRetrievalRagModule -from griptape.loaders import CsvLoader, TextLoader, WebLoader +from griptape.loaders import CsvLoader, PdfLoader, TextLoader, WebLoader from .gtUIBaseRetrievalRagModule import gtUIBaseRetrievalRagModule -loaders = ["TextLoader", "WebLoader", "CsvLoader"] +loaders = ["TextLoader", "CsvLoader", "PdfLoader", "WebLoader"] +input_source_options = ["Text Input", "File Path"] class gtUITextLoaderRetrievalRagModule(gtUIBaseRetrievalRagModule): @@ -13,16 +16,47 @@ class gtUITextLoaderRetrievalRagModule(gtUIBaseRetrievalRagModule): Griptape Text Loader Retrieval Rag Module. Used for the Retrieval Stage of the RAG Engine. """ + SUPPORTED_FORMATS = ( + ".data", + ".env", + ".info", + ".json", + ".log", + ".text", + ".txt", + ".yaml", + ".yml", + ".csv", + ".tsv", + ".md", + ".pdf", + ) + def __init__(self): pass @classmethod def INPUT_TYPES(s): + input_dir = folder_paths.get_input_directory() + files = [ + f + for f in os.listdir(input_dir) + if ( + os.path.isfile(os.path.join(input_dir, f)) + and f.endswith(gtUITextLoaderRetrievalRagModule.SUPPORTED_FORMATS) + ) + ] inputs = super().INPUT_TYPES() inputs["required"].update( { - "loader": (loaders, {"default": "TextLoader"}), + "loader": ( + loaders, + { + "default": loaders[0], + "tooltip": "The type of text to load. If TextLoader or CsvLoader, it won't use the Text Input Port.", + }, + ), } ) inputs["optional"].update( @@ -35,6 +69,22 @@ def INPUT_TYPES(s): "tooltip": "Text to be loaded.", }, ), + "input_source": ( + input_source_options, + { + "default": input_source_options[0], + "tooltip": "Use a specified file path or the text input port.", + "label_on": "Use file path", + "label_off": "Use incoming text", + }, + ), + "file_path": ( + sorted(files), + { + "text_upload": True, + "tooltip": "File to be loaded.", + }, + ), "url": ( "STRING", {"tooltip": "URL to be loaded.", "default": "https://griptape.ai"}, @@ -49,26 +99,34 @@ def create(self, **kwargs): ) text = kwargs.get("text", None) url = kwargs.get("url", "https://griptape.ai") - loader = kwargs.get("loader", "TextLoader") - + loader = kwargs.get("loader", loaders[0]) + input_source = kwargs.get("input_source", input_source_options[0]) params = {} params["query_params"] = self.get_query_params(kwargs) params["vector_store_driver"] = vector_store_driver - if loader == "TextLoader": - # write the text to a temnporary file - with tempfile.NamedTemporaryFile(delete=False) as temp_file: - temp_file.write(text.encode()) - temp_filename = temp_file.name - temp_file.close() - params["loader"] = TextLoader() - params["source"] = temp_filename - params["loader"] = TextLoader() if loader == "WebLoader": params["loader"] = WebLoader() params["source"] = url - if loader == "CsvLoader": - params["loader"] = CsvLoader() - params["source"] = text + else: + if loader == "CsvLoader": + params["loader"] = CsvLoader() + elif loader == "TextLoader": + params["loader"] = TextLoader() + elif loader == "PdfLoader": + params["loader"] = PdfLoader() + + # Get the input source + if input_source == input_source_options[1]: + params["source"] = folder_paths.get_annotated_filepath( + kwargs.get("file_path") + ) + else: + # write the text to a temporary file + with tempfile.NamedTemporaryFile(delete=False) as temp_file: + temp_file.write(text.encode()) + temp_filename = temp_file.name + temp_file.close() + params["source"] = temp_filename module = TextLoaderRetrievalRagModule(**params) return ([module],) diff --git a/nodes/tasks/gtUIExtractionTask.py b/nodes/tasks/gtUIExtractionTask.py new file mode 100644 index 0000000..32deb07 --- /dev/null +++ b/nodes/tasks/gtUIExtractionTask.py @@ -0,0 +1,104 @@ +from griptape.engines import CsvExtractionEngine, JsonExtractionEngine +from griptape.tasks import ExtractionTask + +from ..agent.gtComfyAgent import gtComfyAgent as Agent +from .gtUIBaseTask import gtUIBaseTask + +extraction_engines = ["csv", "json"] + + +class gtUIExtractionTask(gtUIBaseTask): + """ + The Griptape Text Extraction Task + """ + + @classmethod + def INPUT_TYPES(s): + inputs = super().INPUT_TYPES() + inputs["optional"].update( + { + "extraction_type": ( + extraction_engines, + { + "default": "json", + "tooltip": "The type of extraction to perform.", + }, + ), + "column_names": ( + "STRING", + { + "default": "", + "tooltip": "Comma separated list of column names to extract. Example:\n name, age", + }, + ), + "template_schema": ( + "STRING", + { + "default": "", + "multiline": True, + "tooltip": 'Schema template for the json extraction. Example:\n {"name": str, "age": int}', + }, + ), + } + ) + del inputs["required"]["STRING"] + inputs["optional"].update( + { + "STRING": ( + "STRING", + { + "default": "", + "multiline": True, + "tooltip": "Text to extract from. If you are also providing an input_string, this will be added before that.", + }, + ), + } + ) + return inputs + + DESCRIPTION = "Extract text using csv or json." + CATEGORY = "Griptape/Text" + + def run(self, **kwargs): + STRING = kwargs.get("STRING") + input_string = kwargs.get("input_string", None) + agent = kwargs.get("agent", None) + extraction_type = kwargs.get("extraction_type", "json") + column_names_string = kwargs.get("column_names", "") + column_names = [ + column_name.strip() for column_name in column_names_string.split(",") + ] + template_schema = kwargs.get("template_schema", "") + params = {} + + if not agent: + agent = Agent() + prompt_driver = agent.drivers_config.prompt_driver + if extraction_type == "csv": + print("CSV Extraction") + print(column_names) + engine = CsvExtractionEngine( + prompt_driver=prompt_driver, column_names=column_names + ) + elif extraction_type == "json": + engine = JsonExtractionEngine( + prompt_driver=prompt_driver, template_schema=template_schema + ) + + prompt_text = self.get_prompt_text(STRING, input_string) + + task = ExtractionTask(extraction_engine=engine) + try: + agent.add_task(task) + except Exception as e: + print(e) + result = agent.run(prompt_text) + artifacts = result.output_task.output.value + if extraction_type == "csv": + output = [artifact.value.split("\n") for artifact in artifacts] + elif extraction_type == "json": + output = [artifact.value for artifact in artifacts] + return ( + output, + agent, + ) diff --git a/nodes/tasks/gtUIInpaintingImageGenerationTask.py b/nodes/tasks/gtUIInpaintingImageGenerationTask.py new file mode 100644 index 0000000..628c1f2 --- /dev/null +++ b/nodes/tasks/gtUIInpaintingImageGenerationTask.py @@ -0,0 +1,160 @@ +import base64 +import os + +import folder_paths +from griptape.black_forest.drivers.black_forest_image_generation_driver import ( + BlackForestImageGenerationDriver, +) +from griptape.drivers import ( + AmazonBedrockImageGenerationDriver, + AzureOpenAiImageGenerationDriver, + LeonardoImageGenerationDriver, + OpenAiImageGenerationDriver, +) +from griptape.engines import ( + InpaintingImageGenerationEngine, +) +from griptape.loaders import ImageLoader +from griptape.tasks import InpaintingImageGenerationTask + +from ...py.griptape_settings import GriptapeSettings +from ..agent.gtComfyAgent import gtComfyAgent as Agent +from ..utilities import ( + convert_tensor_to_base_64, + image_path_to_output, +) +from .gtUIBaseImageTask import gtUIBaseImageTask + +default_prompt = "{{ input_string }}" + + +class gtUIInpaintingImageGenerationTask(gtUIBaseImageTask): + DESCRIPTION = ( + "Generate an image using an input image, a mask image, and a text prompt." + ) + + @classmethod + def INPUT_TYPES(s): + inputs = super().INPUT_TYPES() + inputs["required"].update( + { + "mask": ("MASK",), + } + ) + inputs["optional"].update({"driver": ("DRIVER",)}) + del inputs["optional"]["agent"] + return inputs + + RETURN_TYPES = ( + "IMAGE", + "STRING", + ) + RETURN_NAMES = ( + "IMAGE", + "FILE_PATH", + ) + + def _model_supports_inpainting(self, driver): + # Map driver types to their supported models and default error messages + supported_models = { + OpenAiImageGenerationDriver: { + "models": ["dall-e-2"], + "default_message": "OpenAI model must be dall-e-2 for inpainting.", + }, + BlackForestImageGenerationDriver: { + "models": ["flux-pro-1.0-fill"], + "default_message": "BlackForest model must be flux-pro-1.0-fill for inpainting.", + }, + LeonardoImageGenerationDriver: { + "models": [], + "default_message": "Leonardo.AI does not support Inpainting. Please choose a different driver.", + }, + AmazonBedrockImageGenerationDriver: { + "models": ["stability.stable-diffusion-xl-v1"], + "default_message": "Amazon Bedrock model must be stability.stable-diffusion-xl-v1 for inpainting.", + }, + AzureOpenAiImageGenerationDriver: { + "models": ["dall-e-2"], + "default_message": "Azure OpenAI model must be dall-e-2 for inpainting.", + }, + } + + # Get the supported models and error message for the driver's type + driver_type = type(driver) + if driver_type in supported_models: + config = supported_models[driver_type] + if driver.model in config["models"]: + return True, "" + else: + return False, config["default_message"] + + # Driver type not supported + return ( + False, + f"Driver type {driver_type.__name__} or model {driver.model} is not supported for image inpainting.", + ) + + def run(self, **kwargs): + STRING = kwargs.get("STRING") + image = kwargs.get("image") + mask = kwargs.get("mask") + driver = kwargs.get("driver", None) + input_string = kwargs.get("input_string", None) + + agent = Agent() + final_image = convert_tensor_to_base_64(image) + final_mask = convert_tensor_to_base_64(mask) + # final_mask = mask_to_image(mask) + if not final_image: + return ("No image provided", agent) + if not final_mask: + return ("No mask provided", agent) + prompt_text = self.get_prompt_text(STRING, input_string) + if not driver: + settings = GriptapeSettings() + OPENAI_API_KEY = settings.get_settings_key_or_use_env("OPENAI_API_KEY") + + driver = OpenAiImageGenerationDriver( + api_key=OPENAI_API_KEY, + model="dall-e-2", + ) + # Check the model can handle InPainting + inpainting_supported, msg = self._model_supports_inpainting(driver) + if not inpainting_supported: + raise ValueError(msg) + + # Quick fix for flux-pro-1.0-fill + if isinstance(driver, BlackForestImageGenerationDriver): + # check the model to make sure it's one that can handle Variation Image Generation + if driver.model == "flux-pro-1.0-fill": + driver.model = "flux-pro-1.0" + + # Create an engine configured to use the driver. + engine = InpaintingImageGenerationEngine( + image_generation_driver=driver, + ) + image_artifact = ImageLoader().parse(base64.b64decode(final_image[0])) + mask_artifact = ImageLoader().parse(base64.b64decode(final_mask[0])) + output_dir = folder_paths.get_temp_directory() + inpainting_task = InpaintingImageGenerationTask( + input=(prompt_text, image_artifact, mask_artifact), + image_generation_engine=engine, + output_dir=output_dir, + ) + + # if deferred_evaluation: + # return (None, "Image Variation Task Created", variation_task) + try: + agent.add_task(inpainting_task) + except Exception as e: + print(e) + try: + result = agent.run() + except Exception as e: + print(e) + filename = result.output_task.output.name + image_path = os.path.join(output_dir, filename) + # Get the image in a format ComfyUI can read + output_image, output_mask = image_path_to_output(image_path) + + return (output_image, image_path) diff --git a/nodes/tasks/gtUIPromptImageVariationTask.py b/nodes/tasks/gtUIPromptImageVariationTask.py index 2ec4a12..082a32d 100644 --- a/nodes/tasks/gtUIPromptImageVariationTask.py +++ b/nodes/tasks/gtUIPromptImageVariationTask.py @@ -2,6 +2,9 @@ import os import folder_paths +from griptape.black_forest.drivers.black_forest_image_generation_driver import ( + BlackForestImageGenerationDriver, +) from griptape.drivers import ( OpenAiImageGenerationDriver, ) @@ -63,6 +66,24 @@ def run(self, **kwargs): api_key=OPENAI_API_KEY, model="dall-e-2", ) + # Check if driver is BlackForestImageGenerationDriver + if isinstance(driver, BlackForestImageGenerationDriver): + # check the model to make sure it's one that can handle Variation Image Generation + if driver.model not in [ + "flux-pro-1.0-canny", + "flux-pro-1.0-depth", + # "flux-dev", + "flux-pro-1.1", + # "flux-pro", + "flux-pro-1.1-ultra", + ]: + raise ValueError( + f"Model {driver.model} is not supported for image variation." + ) + return ( + None, + f"Model {driver.model} is not supported for image variation.", + ) # Create an engine configured to use the driver. engine = VariationImageGenerationEngine( image_generation_driver=driver, diff --git a/nodes/tasks/gtUITask.py b/nodes/tasks/gtUITask.py new file mode 100644 index 0000000..9a6c76b --- /dev/null +++ b/nodes/tasks/gtUITask.py @@ -0,0 +1,102 @@ +from griptape.artifacts import TextArtifact +from griptape.drivers import DummyVectorStoreDriver +from griptape.tasks import PromptTask, ToolkitTask, ToolTask +from griptape.tools import QueryTool, VectorStoreTool + +from ..agent.gtComfyAgent import gtComfyAgent as Agent +from .gtUIBaseTask import gtUIBaseTask + + +class gtUITask(gtUIBaseTask): + DESCRIPTION = "Create a task for an agent." + CATEGORY = "Griptape/Agent" + + @classmethod + def INPUT_TYPES(cls): + inputs = super().INPUT_TYPES() + + # Update optional inputs to include 'tool' and adjust others as necessary + inputs["optional"].update( + { + "tools": ("TOOL_LIST",), + } + ) + return inputs + + def tool_check(self, config, tools): + tool_list = [] + if len(tools) > 0: + # Logic per tool + for tool in tools: + # Check and see if any of the tools are VectorStoreTools + if isinstance(tool, VectorStoreTool): + # Check and see if the driver is a DummyVectorStoreDriver + # If it is, replace it with the agent's vector store driver + if isinstance(tool.vector_store_driver, DummyVectorStoreDriver): + vector_store_driver = config.vector_store_driver + try: + # set the tool's vector store driver to the agent's vector store driver + tool.vector_store_driver = vector_store_driver + except Exception as e: + print(f"Error: {str(e)}") + + # Check and see if any of the tools have been set to off_prompt + off_prompt = False + for tool in tools: + if tool.off_prompt and not off_prompt: + off_prompt = True + if off_prompt: + taskMemoryClient = False + # check and see if QueryTool is in tools + for tool in tools: + if isinstance(tool, QueryTool): + taskMemoryClient = True + if not taskMemoryClient: + tools.append(QueryTool(off_prompt=False)) + tool_list = tools + return tool_list + + def run(self, **kwargs): + STRING = kwargs.get("STRING") + tools = kwargs.get("tools", []) + input_string = kwargs.get("input_string", None) + agent = kwargs.get("agent", None) + prompt_text = self.get_prompt_text(STRING, input_string) + + if prompt_text.strip() == "": + return ("No prompt provided", agent) + + # if the tool is provided, keep going + if not agent: + agent = Agent() + + model, simple_model = agent.model_check() + if simple_model: + response = agent.model_response(model) + return (response, agent) + if len(tools) == 0: + task = PromptTask(prompt_text) + else: + tools = self.tool_check(agent.drivers_config, tools) + if len(tools) == 1: + task = ToolTask(prompt_text, tool=tools[0]) + else: + task = ToolkitTask( + prompt_text, + tools=tools, + ) + try: + agent.add_task(task) + except Exception as e: + print(e) + + result = agent.run() + output = result.output_task.output.value + if isinstance(output, str): + return (output, agent) + elif isinstance(output, list): + output_list = [item.value for item in output] + output_str = "\n\n".join(output_list) + return (output_str, agent) + elif isinstance(output, TextArtifact): + return (output.value, agent) diff --git a/nodes/tasks/gtUITextSummaryTask.py b/nodes/tasks/gtUITextSummaryTask.py index 10bdfc3..6351ffa 100644 --- a/nodes/tasks/gtUITextSummaryTask.py +++ b/nodes/tasks/gtUITextSummaryTask.py @@ -8,7 +8,7 @@ class gtUITextSummaryTask(gtUIBaseTask): DESCRIPTION = "Summarize a text prompt." - CATEGORY = "Griptape/Agent" + CATEGORY = "Griptape/Text" def run(self, **kwargs): STRING = kwargs.get("STRING") diff --git a/nodes/tools/gtUIExtractionTool.py b/nodes/tools/gtUIExtractionTool.py index dd1d799..1a56fc7 100644 --- a/nodes/tools/gtUIExtractionTool.py +++ b/nodes/tools/gtUIExtractionTool.py @@ -10,7 +10,7 @@ class gtUIExtractionTool(gtUIBaseTool): """ - The Griptape Prompt Summary Tool + The Griptape Text Extraction Tool """ @classmethod @@ -49,12 +49,13 @@ def INPUT_TYPES(s): def create(self, **kwargs): prompt_driver = kwargs.get("prompt_driver", None) extraction_type = kwargs.get("extraction_type", "json") - column_names = kwargs.get("column_names", "") + column_names_string = kwargs.get("column_names", "") + column_names = [column_name.strip() for column_name in column_names_string] template_schema = kwargs.get("template_schema", "") params = {} if not prompt_driver: - prompt_driver = OpenAiChatPromptDriver() + prompt_driver = OpenAiChatPromptDriver(model="gpt-4o-mini") if extraction_type == "csv": engine = CsvExtractionEngine( prompt_driver=prompt_driver, column_names=column_names diff --git a/nodes/utilities.py b/nodes/utilities.py index 6d85a3f..7d64c6a 100644 --- a/nodes/utilities.py +++ b/nodes/utilities.py @@ -145,6 +145,7 @@ def load_audio_from_artifact(audio_artifact): return audio_output +# return base64_images def convert_tensor_to_base_64(image): if not isinstance(image, torch.Tensor): raise TypeError("Input must be a PyTorch tensor") @@ -171,7 +172,15 @@ def convert_tensor_to_base_64(image): base64_images = [] for img_array in image.reshape(-1, *image.shape[-3:]): - img = Image.fromarray(img_array) + # Handle single-channel masks + if img_array.shape[-1] == 1: + # Squeeze out the channel dimension and convert to 'L' (8-bit pixels, black and white) + img_array = img_array.squeeze() + img = Image.fromarray(img_array, mode="L") + else: + # Regular RGB/RGBA images + img = Image.fromarray(img_array) + buffer = BytesIO() img.save(buffer, format="PNG") base64_image = base64.b64encode(buffer.getvalue()).decode("utf-8") diff --git a/pyproject.toml b/pyproject.toml index b61bd34..1ea361a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,8 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.11" python-dotenv = "^1.0.1" -griptape = { version = "^0.34.2", extras = ["all"]} +griptape = { version = "^0.34.3", extras = ["all"]} +griptape-black-forest = {git = "https://github.com/griptape-ai/griptape-black-forest.git"} [tool.poetry.group.dev.dependencies] icecream = "^2.1.3" @@ -26,9 +27,9 @@ priority = "explicit" [project] name = "comfyui-griptape" description = "Griptape LLM(Large Language Model) Nodes for ComfyUI." -version = "1.0.20" +version = "1.0.21" license = {file = "LICENSE"} -dependencies = ["griptape[all]==0.34.2", "python-dotenv"] +dependencies = ["griptape[all]==0.34.3", "python-dotenv", "git+https://griptape.com/griptape-ai/griptape-black-forest.git"] [project.urls] Repository = "https://github.com/griptape-ai/ComfyUI-Griptape" diff --git a/requirements.txt b/requirements.txt index 6bda8f7..f00260b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ griptape[all]==0.34.2 python-dotenv +git+https://griptape.com/griptape-ai/griptape-black-forest.git \ No newline at end of file